Practice Python2022-10-19T02:02:05+00:00https://practicepython.orgMichele Pratusevichmichele.pratusevich@gmail.comhttps://practicepython.org/solution/2022/07/24/40-error-checking-solution40 Error Checking Solution2022-07-24T00:00:00+00:002022-07-24T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<h2 id="exercise">Exercise</h2>
<p>Given this solution to <a href="/exercise/2014/04/02/09-guessing-game-one.html">Exercise 9</a>, modify it to have one level of user feedback: if the user does not enter a number between 1 and 9, tell them. Don’t count this guess against the user when counting the number of guesses they used.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">random</span>
<span class="n">number</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">)</span>
<span class="n">number_of_guesses</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Guess a number between 1 and 9: "</span><span class="p">))</span>
<span class="n">number_of_guesses</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">number</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"You needed </span><span class="si">{</span><span class="n">number_of_guesses</span><span class="si">}</span><span class="s"> guesses to guess the number </span><span class="si">{</span><span class="n">number</span><span class="si">}</span><span class="s">"</span><span class="p">)</span></code></pre></figure>
<h2 id="solution">Solution</h2>
<p>Using the terminology from the discussion in the <a href="/exercise/2022/07/17/40-error-checking.html">exercise</a>, the exercise is asking to implement one logical error handling (i.e. making sure the guess is between the numbers 1 and 9) and one Pythonic error handling (making sure the input is strictly a number).</p>
<p>So the solution combines the two techniques discussed.</p>
<p>Firstly, we need to implement an “inner loop” to make sure we have a loop set up to ask the user over and over again for a guess. This is the default - we always ask the user, and only “break” out of the loop when the user’s input meets all of our criteria. The logical error check is implemented with an <code class="language-plaintext highlighter-rouge">if</code> statement: if the guess is between the numbers 1 and 9, we break out of the inner loop. The Pythonic error check is implemented using a <code class="language-plaintext highlighter-rouge">try</code> / <code class="language-plaintext highlighter-rouge">catch</code> statement. Combining these two cases is subtle: we put the logical check inside the <code class="language-plaintext highlighter-rouge">try</code> clause of the Pythonic check - this is <code class="language-plaintext highlighter-rouge">if</code> statement will then only get executed if the previous line (the line with the <code class="language-plaintext highlighter-rouge">int(input())</code>) does not throw a <code class="language-plaintext highlighter-rouge">ValueError</code>. This is a very “Pythonic” way of implemeting the solution to this problem - rather than having two separate checks one after the other, we take advantage of the properties of <code class="language-plaintext highlighter-rouge">try</code> / <code class="language-plaintext highlighter-rouge">catch</code> blocks to do both for us!</p>
<p>Check it out:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">random</span>
<span class="n">number</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">)</span>
<span class="n">number_of_guesses</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Guess a number between 1 and 9: "</span><span class="p">))</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">>=</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">guess</span> <span class="o"><=</span> <span class="mi">9</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Your input must be a number between 1 and 9 inclusive"</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">ValueError</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You must enter a number"</span><span class="p">)</span>
<span class="n">number_of_guesses</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">number</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"You needed </span><span class="si">{</span><span class="n">number_of_guesses</span><span class="si">}</span><span class="s"> guesses to guess the number </span><span class="si">{</span><span class="n">number</span><span class="si">}</span><span class="s">"</span><span class="p">)</span></code></pre></figure>
https://practicepython.org/exercise/2022/07/17/40-error-checking40 Error Checking2022-07-17T00:00:00+00:002022-07-17T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<h2 id="exercise">Exercise</h2>
<p>Given this solution to <a href="/exercise/2014/04/02/09-guessing-game-one.html">Exercise 9</a>, modify it to have one level of user feedback: if the user does not enter a number between 1 and 9, tell them. Don’t count this guess against the user when counting the number of guesses they used.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">random</span>
<span class="n">number</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">)</span>
<span class="n">number_of_guesses</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Guess a number between 1 and 9: "</span><span class="p">))</span>
<span class="n">number_of_guesses</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">number</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"You needed </span><span class="si">{</span><span class="n">number_of_guesses</span><span class="si">}</span><span class="s"> guesses to guess the number </span><span class="si">{</span><span class="n">number</span><span class="si">}</span><span class="s">"</span><span class="p">)</span></code></pre></figure>
<h2 id="discussion">Discussion</h2>
<h3 id="an-example">An Example</h3>
<p>When writing a program that will interact with a person, it is always important to remember that people are not machines. They will accidentally input incorrect data, or will mis-understand instructions given when entering inputs. As programmers, we don’t want any incorrect data to cause our programs to crash.</p>
<p>Let’s first take a the small program from the exercise above (without any error checks) and see what kind of error can happen. If we run the program above, except enter the string “<code class="language-plaintext highlighter-rouge">testing</code>” instead of a number, here is the output error we see:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="n">testing</span>
<span class="o">---------------------------------------------------------------------------</span>
<span class="nb">ValueError</span> <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">)</span>
<span class="o"><</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">1</span><span class="o">-</span><span class="mi">20913</span><span class="n">a3822f0</span><span class="o">></span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="mi">4</span> <span class="n">number_of_guesses</span> <span class="o">=</span> <span class="mi">0</span>
<span class="mi">5</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="o">----></span> <span class="mi">6</span> <span class="n">guess</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Guess a number between 1 and 9: "</span><span class="p">))</span>
<span class="mi">7</span> <span class="n">number_of_guesses</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="mi">8</span> <span class="k">if</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">number</span><span class="p">:</span>
<span class="nb">ValueError</span><span class="p">:</span> <span class="n">invalid</span> <span class="n">literal</span> <span class="k">for</span> <span class="nb">int</span><span class="p">()</span> <span class="k">with</span> <span class="n">base</span> <span class="mi">10</span><span class="p">:</span> <span class="s">'testing'</span></code></pre></figure>
<p>The line <code class="language-plaintext highlighter-rouge">ValueError: invalid literal for int() with base 10: 'testing'</code> is telling us that there is an error with the value being input into the <code class="language-plaintext highlighter-rouge">int()</code> function. Namely, the string “<code class="language-plaintext highlighter-rouge">testing</code>” can’t be converted into an <code class="language-plaintext highlighter-rouge">int()</code>. This makes sense - it’s not an <code class="language-plaintext highlighter-rouge">int</code>! This isn’t a logical error, it’s an error with a data type.</p>
<p>There are many kinds of errors that can happen. Another example of an error is a “logical error” where a user doesn’t follow the instructions given. This doesn’t cause a crash in the program, but leads to a slightly misleading user experience:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="mi">100</span>
<span class="o">>>></span> <span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="mi">1</span>
<span class="o">>>></span> <span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="mi">2</span>
<span class="o">>>></span> <span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="mi">3</span>
<span class="n">You</span> <span class="n">needed</span> <span class="mi">4</span> <span class="n">guesses</span> <span class="n">to</span> <span class="n">guess</span> <span class="n">the</span> <span class="n">number</span> <span class="mi">3</span></code></pre></figure>
<p>Notice how the program lets the user enter the number 100, despite asking for a number between 1 and 9. The number of guesses is counted as 4, although one would argue that the guess 100 was an “invalid guess” and therefore shouldn’t have been counted as a guess. Since there is no way 100 would be the correct answer, might as well not penalize the incorrect guess.</p>
<p>This type of error doesn’t crash our program, but leads to a bad user experience.</p>
<p>The handling of data type / programming errors and logical errors needs a different treatment, which we’ll address in the next two sections.</p>
<h3 id="pythonic-error-handling">Pythonic error handling</h3>
<p>Different programming languages handle programming errors differently. In Python, the mantra is “ask forgiveness, not permission”. What I mean is that we “let” the program execute and throw and error, but “catch” it and do something about it later. This is a bit of an unusual paradigm - wouldn’t it make more sense to NEVER have the program throw an error in the first place? Sure, that can be done as well. In Python however, throwing an error isn’t a big deal, as long as we catch it. It also makes the code clear to understand which error we CAN handle and which we CANNOT. In Python, when the program throws an error, that error is called an <code class="language-plaintext highlighter-rouge">Exception</code>.</p>
<p>The mechanism to “catch” an error in the program is called a <code class="language-plaintext highlighter-rouge">try</code> / <code class="language-plaintext highlighter-rouge">catch</code> block. The official Python documentation has a section about <a href="https://docs.python.org/3/tutorial/errors.html#handling-exceptions">handing exceptions</a> that goes into detail about what exceptions are and how to extend them, for more detailed reading.</p>
<p>The way to think about a <code class="language-plaintext highlighter-rouge">try</code> / <code class="language-plaintext highlighter-rouge">catch</code> block is that the “try” section is asking the program to execute something, and the “catch” block is executed if the code in the “try” section throws an exception. When we write a “catch” block, we always should specify what kind of exception we want to catch. In the example above, when the string <code class="language-plaintext highlighter-rouge">testing</code> was entered instead of a number, the <code class="language-plaintext highlighter-rouge">int()</code> code throws a <code class="language-plaintext highlighter-rouge">ValueError</code> exception. So if we want to catch that error, we specify it specifically:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">try</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Guess a number between 1 and 9: "</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"You entered </span><span class="si">{</span><span class="n">guess</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">ValueError</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"ValueError is thrown"</span><span class="p">)</span></code></pre></figure>
<p>And we see the following:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="mi">8</span>
<span class="n">You</span> <span class="n">entered</span> <span class="mi">8</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">Guess</span> <span class="n">a</span> <span class="n">number</span> <span class="n">between</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">9</span><span class="p">:</span> <span class="n">testing</span>
<span class="nb">ValueError</span> <span class="ow">is</span> <span class="n">thrown</span></code></pre></figure>
<p>Notice how the program didn’t crash spectacularly in the second case - it simply kept going! In the first case (when everything was OK with the input) the code in the “catch” block did not execute, and we didn’t need it to.</p>
<p>Adding a <code class="language-plaintext highlighter-rouge">try</code>/<code class="language-plaintext highlighter-rouge">catch</code> block to the code in the exercise will require some playing around with loops, but it can be done! Check out the <a href="/solution/2022/07/24/40-error-checking-solution.html">solution</a> to see how.</p>
<h3 id="logical-error-handling">Logical error handling</h3>
<p>The <code class="language-plaintext highlighter-rouge">try</code>/<code class="language-plaintext highlighter-rouge">catch</code> paradigm detailed in the section above doesn’t work for logical program errors. Why? Because in that case, there is no exception thrown! In the example of a user entering 100 when asked for a number between 1 and 9, the program continues on it’s way, so there’s nothing to catch.</p>
<p>In the case of checking for logical errors, we need to be a bit more clever when writing our programs. Namely, we need to write more code! In the case of the example program above, if we truly don’t want to allow guesses that are not between 1 and 9, we need to check for that case:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">guess</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Guess a number between 1 and 9: "</span><span class="p">))</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o"><</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">guess</span> <span class="o">></span> <span class="mi">9</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Guess again!"</span><span class="p">)</span></code></pre></figure>
<p>In this snippet, we use an <code class="language-plaintext highlighter-rouge">if</code> statement to check whether the user input guess satisfies our standards. Of course, to finish this exercise, we need to account for not counting the number of guesses in this case, and make sure we ask the user to enter a new number. Check out the <a href="/solution/2022/07/24/40-error-checking-solution.html">solution</a> to see how.</p>
https://practicepython.org/solution/2022/06/23/39-character-input-datetime-solution39 Character Input Datetime Solution2022-06-23T00:00:00+00:002022-06-23T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<h2 id="exercise">Exercise</h2>
<p>Implement the same exercise as <a href="/exercise/2014/01/29/01-character-input.html">Exercise 1</a> (Create a program that asks the user to enter their name and their age. Print out a message addressed to them that tells them the year that they will turn 100 years old), except don’t explicitly write out the year. Use the built-in Python <code class="language-plaintext highlighter-rouge">datetime</code> library to make the code you write work during every year, not just the one we are currently in.</p>
<h2 id="solution">Solution</h2>
<p>To figure out the year in which someone will turn 100, we need to take the current year, subtract their current age, and add 100. We use the <code class="language-plaintext highlighter-rouge">datetime</code> library to get the current year, the <code class="language-plaintext highlighter-rouge">input()</code> function (see <a href="/exercise/2014/01/29/01-character-input.html">exercise 1</a>) to ask the user their name and age, and f-strings (see <a href="/exercise/2022/03/06/38-f-strings.html">exercise 38</a>) to print out the result.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">datetime</span>
<span class="n">current_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="n">now</span><span class="p">().</span><span class="n">year</span>
<span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"What is your name? "</span><span class="p">)</span>
<span class="n">age</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"How old are you? "</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s">, you will be 100 years old in </span><span class="si">{</span><span class="n">current_year</span> <span class="o">-</span> <span class="n">age</span> <span class="o">+</span> <span class="mi">100</span><span class="si">}</span><span class="s">"</span><span class="p">)</span></code></pre></figure>
<p>Take a look at the difference between this solution and the hard-coded one in <a href="/solution/2014/02/05/01-character-input-solutions.html">exercise 1</a>, where the year does not update automatically.</p>
https://practicepython.org/exercise/2022/03/20/39-character-input-datetime39 Character Input Datetime2022-03-20T00:00:00+00:002022-03-20T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<h2 id="exercise">Exercise</h2>
<p>Implement the same exercise as <a href="/exercise/2014/01/29/01-character-input.html">Exercise 1</a> (Create a program that asks the user to enter their name and their age. Print out a message addressed to them that tells them the year that they will turn 100 years old), except don’t explicitly write out the year. Use the built-in Python <code class="language-plaintext highlighter-rouge">datetime</code> library to make the code you write work during every year, not just the one we are currently in.</p>
<h2 id="discussion">Discussion</h2>
<p>Concepts:</p>
<ul>
<li>Modules</li>
<li><code class="language-plaintext highlighter-rouge">datetime</code> module</li>
</ul>
<h3 id="datetime-and-modules"><code class="language-plaintext highlighter-rouge">datetime</code> (and Modules)</h3>
<p>One very common thing programs are used for is to perform operations with dates and times. How hard is it for you to count the number of days between two dates? Or count the number of seconds between two specific times? Good thing someone else wrote code that already does this for us! Python distributes these other useful pieces of code as built-in libraries or <em>modules</em>. It comes standard with any Python installation, so no additional installation is required.</p>
<p>The built-in library in Python used for working with dates and times is called <a href="https://docs.python.org/3/library/datetime.html"><code class="language-plaintext highlighter-rouge">datetime</code></a>. The structures and functions in the library will be useful to solve the exercise.</p>
<p>To use a built-in library or module, we need to import this module into our current code. (For another use case for modules, see <a href="/exercise/2014/04/02/09-guessing-game-one.html">Exercise 9</a>)</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="kn">import</span> <span class="nn">datetime</span></code></pre></figure>
<p>Now, we can use the <code class="language-plaintext highlighter-rouge">datetime</code> library to construct dates and manipulate them. The <a href="https://docs.python.org/3/library/datetime.html">full documentation for <code class="language-plaintext highlighter-rouge">datetime</code></a> has a comprehensive list of functions available in this library, but I will highlight a few common ones.</p>
<h3 id="todays-date">Today’s date</h3>
<p>To get today’s date, use the utility function:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">>>></span> <span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="n">now</span><span class="p">()</span>
<span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">(</span><span class="mi">2022</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">19</span><span class="p">,</span> <span class="mi">18</span><span class="p">,</span> <span class="mi">40</span><span class="p">,</span> <span class="mi">45</span><span class="p">,</span> <span class="mi">276070</span><span class="p">)</span></code></pre></figure>
<p>which returns a <code class="language-plaintext highlighter-rouge">datetime</code> object that we can manipulate. For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">>>></span> <span class="n">now</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="n">now</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">now</span><span class="p">.</span><span class="n">year</span>
<span class="mi">2022</span>
<span class="o">>>></span> <span class="n">now</span><span class="p">.</span><span class="n">month</span>
<span class="mi">2</span></code></pre></figure>
<h3 id="time-differences">Time Differences</h3>
<p>We can also take the delta between two times:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">>>></span> <span class="kn">import</span> <span class="nn">datetime</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">time</span>
<span class="o">>>></span> <span class="n">now</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="n">now</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">later</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">.</span><span class="n">datetime</span><span class="p">.</span><span class="n">now</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">later</span> <span class="o">-</span> <span class="n">now</span>
<span class="n">datetime</span><span class="p">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">microseconds</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span></code></pre></figure>
<p><em>In the above sample code, we used <code class="language-plaintext highlighter-rouge">import time</code> from the Python <a href="https://docs.python.org/3/library/time.html#time.sleep">time</a> library to pause the program for exactly 2 seconds.</em></p>
https://practicepython.org/solution/2022/03/13/38-f-strings-solutionf Strings Solution2022-03-13T00:00:00+00:002022-03-13T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<h2 id="exercise">Exercise</h2>
<p>Implement the same exercise as <a href="/exercise/2014/01/29/01-character-input.html">Exercise 1</a> (Create a program that asks the user to enter their name and their age. Print out a message addressed to them that tells them the year that they will turn 100 years old), except use f-strings instead of the <code class="language-plaintext highlighter-rouge">+</code> operator to print the resulting output message.</p>
<h2 id="solution">Solution</h2>
<p>In the <a href="/solution/2014/02/05/01-character-input-solutions.html">exercise 1 solution</a>, we had to convert the variable <code class="language-plaintext highlighter-rouge">year</code> into a string so that we could construct a full string and print it. Instead, here we use f-strings to directly convert the variable <code class="language-plaintext highlighter-rouge">year</code> into a string using Python internals.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"What is your name: "</span><span class="p">)</span>
<span class="n">age</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"How old are you: "</span><span class="p">))</span>
<span class="n">year</span> <span class="o">=</span> <span class="mi">2014</span> <span class="o">-</span> <span class="n">age</span> <span class="o">+</span> <span class="mi">100</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s">, you will be 100 years old in the year </span><span class="si">{</span><span class="n">year</span><span class="si">}</span><span class="s">"</span><span class="p">)</span></code></pre></figure>
https://practicepython.org/exercise/2022/03/06/38-f-stringsf Strings2022-03-06T00:00:00+00:002022-03-06T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<h2 id="exercise">Exercise</h2>
<p>Implement the same exercise as <a href="/exercise/2014/01/29/01-character-input.html">Exercise 1</a> (Create a program that asks the user to enter their name and their age. Print out a message addressed to them that tells them the year that they will turn 100 years old), except use f-strings instead of the <code class="language-plaintext highlighter-rouge">+</code> operator to print the resulting output message.</p>
<h2 id="discussion">Discussion</h2>
<p>One very common operation programmers need to do is display information in the form of text output. In Python we use the <code class="language-plaintext highlighter-rouge">print()</code> function for this, but we need to keep one thing in mind: the <code class="language-plaintext highlighter-rouge">print()</code> function only takes strings. That means, when we want to display an integer, we need to convert it to a string before passing it to the <code class="language-plaintext highlighter-rouge">print()</code> function. When we have complicated numbers to display, this becomes burdensome.</p>
<p>Instead, there is a built-in Python functionality called <a href="https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals">f-strings</a>, short for <em>formatted string literals</em> that solve the problem for us!</p>
<h3 id="variables">Variables</h3>
<p>For me, the most common use of f-strings is to automatically display variables in a string. The mechanism to do this is:</p>
<ol>
<li>Put the character “f” before the <code class="language-plaintext highlighter-rouge">"</code> from the string</li>
<li>Put the variable name (or expression) between <code class="language-plaintext highlighter-rouge">{ }</code> inside the string.</li>
</ol>
<p>For example, the following code displays my favorite color in a sentence:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">color</span> <span class="o">=</span> <span class="s">"orange"</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"My favorite color is </span><span class="si">{</span><span class="n">color</span><span class="si">}</span><span class="s">."</span><span class="p">)</span>
<span class="n">My</span> <span class="n">favorite</span> <span class="n">color</span> <span class="ow">is</span> <span class="n">orange</span><span class="p">.</span></code></pre></figure>
<p>No need for concatenating strings with the <code class="language-plaintext highlighter-rouge">+</code> sign! Similarly for numbers:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">number</span> <span class="o">=</span> <span class="mi">5</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"The number is </span><span class="si">{</span><span class="n">number</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="n">The</span> <span class="n">number</span> <span class="ow">is</span> <span class="mi">5</span></code></pre></figure>
<p>There are all kinds of options for formatting decimals too - how many numbers after the decimal point, pad with zeroes, etc. that <a href="https://docs.python.org/3/library/string.html#formatspec">the official documentation</a> goes into in great detail, <a href="https://docs.python.org/3/library/string.html#format-examples">with examples</a>, so I won’t do that here. Note that the examples are shown with the “old” <code class="language-plaintext highlighter-rouge">.format()</code> way of string formatting in Python, but it applies to f-strings as well.</p>
<h3 id="expressions">Expressions</h3>
<p>The really truly versatile thing that f-strings allow you to do is display <em>expressions</em> and not just variables. In some cases this is very useful, mostly for readability:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"2 + 2 = </span><span class="si">{</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">2</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="mi">2</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">=</span> <span class="mi">4</span></code></pre></figure>
<p>Hopefully with f-strings, you have a more compact way of displaying information to the terminal!</p>
https://practicepython.org/solution/2022/02/27/37-functions-refactor-solution37 Functions Refactor Solution2022-02-27T00:00:00+00:002022-02-27T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>This exercise asked you to refactor this code snippet to refactor (taken from a correct but very repeated solution to <a href="/exercise/2014/12/27/24-draw-a-game-board.html">exercise 24</a> on this website):</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| | | |"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| | | |"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| | | |"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span></code></pre></figure>
<p><em>Hint: Think about a way to refactor this using functions where generating an 8x8 or a 19x19 grid is a single change to a function call!</em></p>
<h2 id="solution">Solution</h2>
<p>What we can see right away is the repeated structure of the vertical and horizontal lines. Our strategy therefore is going to be to write one function for the vertical lines, and one function for the horizontal lines.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">print_verticals</span><span class="p">(</span><span class="n">grid_size</span><span class="p">):</span>
<span class="n">vertical_string</span> <span class="o">=</span> <span class="s">"|"</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">grid_size</span><span class="p">):</span>
<span class="n">vertical_string</span> <span class="o">+=</span> <span class="s">" |"</span>
<span class="k">print</span><span class="p">(</span><span class="n">vertical_string</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">print_horizontals</span><span class="p">(</span><span class="n">grid_size</span><span class="p">):</span>
<span class="n">horiz_string</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">grid_size</span><span class="p">):</span>
<span class="n">horiz_string</span> <span class="o">+=</span> <span class="s">" ---"</span>
<span class="k">print</span><span class="p">(</span><span class="n">horiz_string</span><span class="p">)</span></code></pre></figure>
<p>This way, with these two functions, we can print the grid in a repeatable way for a square grid, just by changing a single variable (<code class="language-plaintext highlighter-rouge">grid_size</code>):</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">grid_size</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">print_horizontals</span><span class="p">(</span><span class="n">grid_size</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">grid_size</span><span class="p">):</span>
<span class="n">print_verticals</span><span class="p">(</span><span class="n">grid_size</span><span class="p">)</span>
<span class="n">print_horizontals</span><span class="p">(</span><span class="n">grid_size</span><span class="p">)</span></code></pre></figure>
<p>The cool part about this function split is that to make an asymmetrical grid, we instead use two variables <code class="language-plaintext highlighter-rouge">grid_size_x</code> and <code class="language-plaintext highlighter-rouge">grid_size_y</code> to control how many squares in the <code class="language-plaintext highlighter-rouge">x</code> and <code class="language-plaintext highlighter-rouge">y</code> direction we want, without having to change any of our printing code:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">grid_size_x</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">grid_size_y</span> <span class="o">=</span> <span class="mi">5</span>
<span class="n">print_horizontals</span><span class="p">(</span><span class="n">grid_size_x</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">grid_size_y</span><span class="p">):</span>
<span class="n">print_verticals</span><span class="p">(</span><span class="n">grid_size_x</span><span class="p">)</span>
<span class="n">print_horizontals</span><span class="p">(</span><span class="n">grid_size_x</span><span class="p">)</span></code></pre></figure>
<p>prints out:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> --- --- ---
| | | |
--- --- ---
| | | |
--- --- ---
| | | |
--- --- ---
| | | |
--- --- ---
| | | |
--- --- ---
</code></pre></div></div>
<p>Happy coding!</p>
https://practicepython.org/exercise/2022/02/20/37-functions-refactor37 Functions Refactor2022-02-20T00:00:00+00:002022-02-20T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>One area of confusion for new coders is the concept of functions (which have been addressed on this blog in <a href="/exercise/2014/04/16/11-check-primality-functions.html">exercise 11</a> for example). So in this exercise, we will be stretching our functions muscle by <em>refactoring</em> an existing code snippet into using functions.</p>
<p>Here is the code snippet to refactor (taken from a correct but very repeated solution to <a href="/exercise/2014/12/27/24-draw-a-game-board.html">exercise 24</a> on this website):</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| | | |"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| | | |"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| | | |"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- --- ---"</span><span class="p">)</span></code></pre></figure>
<p><em>Hint: Think about a way to refactor this using functions where generating an 8x8 or a 19x19 grid is a single change to a function call!</em></p>
<h2 id="discussion">Discussion</h2>
<p>Oftentimes as we write a program, we find ourselves wanting to reuse the same piece of code over and over again. This is a great use case for a function, and in particular, re-writing a piece of code (known as <em>refactoring</em>) to use a function. We often refactor code to use a function or functions to not repeat similar code segments, and make the code less error-prone.</p>
<p>As an example of how to do this, let’s take the following code snippet for playing the <a href="/exercise/2014/03/26/08-rock-paper-scissors.html">Rock, Paper, Scissors game from exercise 8</a> and refactor.</p>
<p>The following snippet is a complete piece of code for playing the game Rock Paper Scissors.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">player1</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">player1</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"rock"</span><span class="p">,</span> <span class="s">"paper"</span><span class="p">,</span> <span class="s">"scissors"</span><span class="p">]:</span>
<span class="n">player1</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"player1 make your move (rock, paper, scissors): "</span><span class="p">)</span>
<span class="n">player2</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">player2</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"rock"</span><span class="p">,</span> <span class="s">"paper"</span><span class="p">,</span> <span class="s">"scissors"</span><span class="p">]:</span>
<span class="n">player2</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"player2 make your move (rock, paper, scissors): "</span><span class="p">)</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">if</span> <span class="n">player1</span> <span class="o">==</span> <span class="n">player2</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"The outcome is a tie"</span>
<span class="k">elif</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">and</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"scissors"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"paper"</span> <span class="ow">and</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"rock"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">and</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"paper"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">and</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"scissors"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">elif</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"paper"</span> <span class="ow">and</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"rock"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">elif</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">and</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"paper"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">print</span><span class="p">(</span><span class="n">winner_message</span><span class="p">)</span>
<span class="n">again</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">again</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"y"</span><span class="p">,</span> <span class="s">"n"</span><span class="p">]:</span>
<span class="n">again</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Do you want to play again? (y/n): "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">again</span> <span class="o">==</span> <span class="s">"n"</span><span class="p">:</span>
<span class="k">break</span></code></pre></figure>
<p>When looking at this piece of code, we see two things that stand out as “repeated blocks”:</p>
<ol>
<li>Asking for player 1’s input and asking for player 2’s input is an identical piece of code</li>
<li>The <code class="language-plaintext highlighter-rouge">if</code>/<code class="language-plaintext highlighter-rouge">else</code> checking for who is the winner has many doubled checks</li>
</ol>
<p>So let’s use these two as inspiration for refactoring. First, getting input from either player - let’s put that code into a separate function:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">get_move</span><span class="p">():</span>
<span class="n">move</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">move</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"rock"</span><span class="p">,</span> <span class="s">"paper"</span><span class="p">,</span> <span class="s">"scissors"</span><span class="p">]:</span>
<span class="n">move</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"player2 make your move (rock, paper, scissors): "</span><span class="p">)</span>
<span class="k">return</span> <span class="n">move</span></code></pre></figure>
<p>Now we can use this function in our new gameplay for Rock Paper Scissors:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">get_move</span><span class="p">():</span>
<span class="n">move</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">move</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"rock"</span><span class="p">,</span> <span class="s">"paper"</span><span class="p">,</span> <span class="s">"scissors"</span><span class="p">]:</span>
<span class="n">move</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"player2 make your move (rock, paper, scissors): "</span><span class="p">)</span>
<span class="k">return</span> <span class="n">move</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">player1</span> <span class="o">=</span> <span class="n">get_move</span><span class="p">()</span>
<span class="n">player2</span> <span class="o">=</span> <span class="n">get_move</span><span class="p">()</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">if</span> <span class="n">player1</span> <span class="o">==</span> <span class="n">player2</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"The outcome is a tie"</span>
<span class="k">elif</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">and</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"scissors"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"paper"</span> <span class="ow">and</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"rock"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">and</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"paper"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">and</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"scissors"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">elif</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"paper"</span> <span class="ow">and</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"rock"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">elif</span> <span class="n">player2</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">and</span> <span class="n">player1</span> <span class="o">==</span> <span class="s">"paper"</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">print</span><span class="p">(</span><span class="n">winner_message</span><span class="p">)</span>
<span class="n">again</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">again</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"y"</span><span class="p">,</span> <span class="s">"n"</span><span class="p">]:</span>
<span class="n">again</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Do you want to play again? (y/n): "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">again</span> <span class="o">==</span> <span class="s">"n"</span><span class="p">:</span>
<span class="k">break</span></code></pre></figure>
<p>When looking at the big <code class="language-plaintext highlighter-rouge">while True</code> loop we can see two calls of the function <code class="language-plaintext highlighter-rouge">get_move()</code>, which makes it clear what we are doing for each player’s move.</p>
<p>Now let’s tackle the winner-checking as a function. This is a bit more subtle for how to refactor. One thing we notice from the existing code is that we have two sets of conditions: one to check whether player 1 is the winner, and one to check whether player 2 is the winner. However, this code is duplicated. Instead, what we will do is write a function that will return “is the first player the winner” and call that function twice.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">is_first_the_winner</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">second</span><span class="p">):</span>
<span class="k">if</span> <span class="n">first</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">and</span> <span class="n">second</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">or</span> \
<span class="n">first</span> <span class="o">==</span> <span class="s">"paper"</span> <span class="ow">and</span> <span class="n">second</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">or</span> \
<span class="n">first</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">and</span> <span class="n">second</span> <span class="o">==</span> <span class="s">"paper"</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">True</span>
<span class="k">return</span> <span class="bp">False</span></code></pre></figure>
<p>Now we refactor our main code with this helper function:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">get_move</span><span class="p">():</span>
<span class="n">move</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">move</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"rock"</span><span class="p">,</span> <span class="s">"paper"</span><span class="p">,</span> <span class="s">"scissors"</span><span class="p">]:</span>
<span class="n">move</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"player2 make your move (rock, paper, scissors): "</span><span class="p">)</span>
<span class="k">return</span> <span class="n">move</span>
<span class="k">def</span> <span class="nf">is_first_the_winner</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">second</span><span class="p">):</span>
<span class="k">if</span> <span class="n">first</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">and</span> <span class="n">second</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">or</span> \
<span class="n">first</span> <span class="o">==</span> <span class="s">"paper"</span> <span class="ow">and</span> <span class="n">second</span> <span class="o">==</span> <span class="s">"rock"</span> <span class="ow">or</span> \
<span class="n">first</span> <span class="o">==</span> <span class="s">"scissors"</span> <span class="ow">and</span> <span class="n">second</span> <span class="o">==</span> <span class="s">"paper"</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">True</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">player1</span> <span class="o">=</span> <span class="n">get_move</span><span class="p">()</span>
<span class="n">player2</span> <span class="o">=</span> <span class="n">get_move</span><span class="p">()</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">if</span> <span class="n">player1</span> <span class="o">==</span> <span class="n">player2</span><span class="p">:</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"The outcome is a tie"</span>
<span class="k">elif</span> <span class="n">is_first_the_winner</span><span class="p">(</span><span class="n">player1</span><span class="p">,</span> <span class="n">player2</span><span class="p">):</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player1 is the winner"</span>
<span class="k">elif</span> <span class="n">is_first_the_winner</span><span class="p">(</span><span class="n">player2</span><span class="p">,</span> <span class="n">player1</span><span class="p">):</span>
<span class="n">winner_message</span> <span class="o">=</span> <span class="s">"player2 is the winner"</span>
<span class="k">print</span><span class="p">(</span><span class="n">winner_message</span><span class="p">)</span>
<span class="n">again</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="n">again</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">"y"</span><span class="p">,</span> <span class="s">"n"</span><span class="p">]:</span>
<span class="n">again</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Do you want to play again? (y/n): "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">again</span> <span class="o">==</span> <span class="s">"n"</span><span class="p">:</span>
<span class="k">break</span></code></pre></figure>
<p>Now what we have is an easy-to-read program with two functions that don’t have any repeated code! Happy coding.</p>
https://practicepython.org/solution/2022/02/13/36-birthday-plots-solutions36 Birthday Plots Solutions2022-02-13T00:00:00+00:002022-02-13T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In the <a href="/exercise/2017/02/28/35-birthday-months.html">previous exercise</a> we counted how many birthdays there are in each month in our dictionary of birthdays. In this exercise, use the <a href="http://bokeh.pydata.org/en/latest/">bokeh</a> Python library to plot a histogram of which months the scientists have birthdays in using <a href="/assets/scientist_birthdays.json">my scientist birthday JSON file</a>.</p>
<h2 id="solution">Solution</h2>
<p>In our solution we need to:</p>
<ol>
<li>Load the JSON data</li>
<li>Count the number of months</li>
<li>Plot with Bokeh</li>
</ol>
<p>There are a few ways to do this, but here is mine:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">math</span>
<span class="kn">from</span> <span class="nn">bokeh.plotting</span> <span class="kn">import</span> <span class="n">figure</span><span class="p">,</span> <span class="n">show</span><span class="p">,</span> <span class="n">output_file</span>
<span class="n">DATA_FILE</span> <span class="o">=</span> <span class="s">"scientist_birthdays.json"</span>
<span class="n">output_file</span><span class="p">(</span><span class="s">"plot.html"</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">DATA_FILE</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">DATA</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="n">num_to_string</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">1</span><span class="p">:</span> <span class="s">"January"</span><span class="p">,</span>
<span class="mi">2</span><span class="p">:</span> <span class="s">"February"</span><span class="p">,</span>
<span class="mi">3</span><span class="p">:</span> <span class="s">"March"</span><span class="p">,</span>
<span class="mi">4</span><span class="p">:</span> <span class="s">"April"</span><span class="p">,</span>
<span class="mi">5</span><span class="p">:</span> <span class="s">"May"</span><span class="p">,</span>
<span class="mi">6</span><span class="p">:</span> <span class="s">"June"</span><span class="p">,</span>
<span class="mi">7</span><span class="p">:</span> <span class="s">"July"</span><span class="p">,</span>
<span class="mi">8</span><span class="p">:</span> <span class="s">"August"</span><span class="p">,</span>
<span class="mi">9</span><span class="p">:</span> <span class="s">"September"</span><span class="p">,</span>
<span class="mi">10</span><span class="p">:</span> <span class="s">"October"</span><span class="p">,</span>
<span class="mi">11</span><span class="p">:</span> <span class="s">"November"</span><span class="p">,</span>
<span class="mi">12</span><span class="p">:</span> <span class="s">"December"</span>
<span class="p">}</span>
<span class="n">months</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">birthday_string</span> <span class="ow">in</span> <span class="n">DATA</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="n">month</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">birthday_string</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"/"</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">months</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">num_to_string</span><span class="p">[</span><span class="n">month</span><span class="p">])</span>
<span class="n">months</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="n">months</span><span class="p">)</span>
<span class="n">months</span><span class="p">,</span> <span class="n">counts</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="o">*</span><span class="n">months</span><span class="p">.</span><span class="n">items</span><span class="p">()))</span>
<span class="n">categories</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">num_to_string</span><span class="p">.</span><span class="n">values</span><span class="p">())</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">figure</span><span class="p">(</span><span class="n">x_range</span><span class="o">=</span><span class="n">categories</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s">"Scientists' Birthday Months"</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">xaxis</span><span class="p">.</span><span class="n">major_label_orientation</span> <span class="o">=</span> <span class="n">math</span><span class="p">.</span><span class="n">pi</span><span class="o">/</span><span class="mi">4</span>
<span class="n">p</span><span class="p">.</span><span class="n">vbar</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">months</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="n">counts</span><span class="p">)</span>
<span class="n">show</span><span class="p">(</span><span class="n">p</span><span class="p">)</span></code></pre></figure>
<p>And my output plot looks like this (you must have Javascript enabled to see it):</p>
<div class="bk-root" id="24430e12-d573-4c12-b211-59666af0983f" data-root-id="1331"></div>
<script type="application/json" id="1499">
{"7c2f2841-1062-4546-b0b9-1f0313d05413":{"defs":[],"roots":{"references":[{"attributes":{},"id":"1374","type":"CategoricalTickFormatter"},{"attributes":{"fill_alpha":{"value":0.1},"fill_color":{"value":"#1f77b4"},"hatch_alpha":{"value":0.1},"line_alpha":{"value":0.1},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"x":{"field":"x"}},"id":"1365","type":"VBar"},{"attributes":{},"id":"1376","type":"UnionRenderers"},{"attributes":{"source":{"id":"1363"}},"id":"1368","type":"CDSView"},{"attributes":{},"id":"1372","type":"AllLabels"},{"attributes":{"fill_alpha":{"value":0.2},"fill_color":{"value":"#1f77b4"},"hatch_alpha":{"value":0.2},"line_alpha":{"value":0.2},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"x":{"field":"x"}},"id":"1366","type":"VBar"},{"attributes":{"tools":[{"id":"1349"},{"id":"1350"},{"id":"1351"},{"id":"1352"},{"id":"1353"},{"id":"1354"}]},"id":"1356","type":"Toolbar"},{"attributes":{"fill_color":{"value":"#1f77b4"},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"x":{"field":"x"}},"id":"1364","type":"VBar"},{"attributes":{},"id":"1377","type":"Selection"},{"attributes":{"bottom_units":"screen","coordinates":null,"fill_alpha":0.5,"fill_color":"lightgrey","group":null,"left_units":"screen","level":"overlay","line_alpha":1.0,"line_color":"black","line_dash":[4,4],"line_width":2,"right_units":"screen","syncable":false,"top_units":"screen"},"id":"1355","type":"BoxAnnotation"},{"attributes":{"factors":["January","February","March","April","May","June","July","August","September","October","November","December"]},"id":"1334","type":"FactorRange"},{"attributes":{},"id":"1338","type":"CategoricalScale"},{"attributes":{},"id":"1343","type":"CategoricalTicker"},{"attributes":{},"id":"1371","type":"BasicTickFormatter"},{"attributes":{},"id":"1336","type":"DataRange1d"},{"attributes":{"coordinates":null,"group":null,"text":"Scientists' Birthday Months"},"id":"1332","type":"Title"},{"attributes":{"coordinates":null,"data_source":{"id":"1363"},"glyph":{"id":"1364"},"group":null,"hover_glyph":null,"muted_glyph":{"id":"1366"},"nonselection_glyph":{"id":"1365"},"view":{"id":"1368"}},"id":"1367","type":"GlyphRenderer"},{"attributes":{"coordinates":null,"formatter":{"id":"1371"},"group":null,"major_label_policy":{"id":"1372"},"ticker":{"id":"1346"}},"id":"1345","type":"LinearAxis"},{"attributes":{},"id":"1375","type":"AllLabels"},{"attributes":{},"id":"1340","type":"LinearScale"},{"attributes":{},"id":"1353","type":"ResetTool"},{"attributes":{"axis":{"id":"1342"},"coordinates":null,"group":null,"ticker":null},"id":"1344","type":"Grid"},{"attributes":{"below":[{"id":"1342"}],"center":[{"id":"1344"},{"id":"1348"}],"left":[{"id":"1345"}],"renderers":[{"id":"1367"}],"title":{"id":"1332"},"toolbar":{"id":"1356"},"x_range":{"id":"1334"},"x_scale":{"id":"1338"},"y_range":{"id":"1336"},"y_scale":{"id":"1340"}},"id":"1331","subtype":"Figure","type":"Plot"},{"attributes":{},"id":"1352","type":"SaveTool"},{"attributes":{},"id":"1354","type":"HelpTool"},{"attributes":{"overlay":{"id":"1355"}},"id":"1351","type":"BoxZoomTool"},{"attributes":{"coordinates":null,"formatter":{"id":"1374"},"group":null,"major_label_orientation":0.7853981633974483,"major_label_policy":{"id":"1375"},"ticker":{"id":"1343"}},"id":"1342","type":"CategoricalAxis"},{"attributes":{},"id":"1349","type":"PanTool"},{"attributes":{},"id":"1350","type":"WheelZoomTool"},{"attributes":{"data":{"top":[1,1,1],"x":["March","December","January"]},"selected":{"id":"1377"},"selection_policy":{"id":"1376"}},"id":"1363","type":"ColumnDataSource"},{"attributes":{},"id":"1346","type":"BasicTicker"},{"attributes":{"axis":{"id":"1345"},"coordinates":null,"dimension":1,"group":null,"ticker":null},"id":"1348","type":"Grid"}],"root_ids":["1331"]},"title":"Bokeh Application","version":"2.4.2"}}
</script>
<script type="text/javascript">
(function() {
const fn = function() {
Bokeh.safely(function() {
(function(root) {
function embed_document(root) {
const docs_json = document.getElementById('1499').textContent;
const render_items = [{"docid":"7c2f2841-1062-4546-b0b9-1f0313d05413","root_ids":["1331"],"roots":{"1331":"24430e12-d573-4c12-b211-59666af0983f"}}];
root.Bokeh.embed.embed_items(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
});
};
if (document.readyState != "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
})();
</script>
<p>One interesting syntax is the line <code class="language-plaintext highlighter-rouge">months, counts = list(zip(*months.items()))</code>. What this does is takes the <code class="language-plaintext highlighter-rouge">months</code> dictionary, returns it as tuples, then unzips them into two lists. We can see this output by looking at the individual outputs one at a time in the shell:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>In [1]: months
Out[1]: Counter({'March': 1, 'December': 1, 'January': 1})
In [2]: months.items()
Out[2]: dict_items([('March', 1), ('December', 1), ('January', 1)])
In [3]: zip(*months.items())
Out[3]: <zip at 0x7fed18fd8040>
In [4]: list(zip(*months.items()))
Out[4]: [('March', 'December', 'January'), (1, 1, 1)]
</code></pre></div></div>
<p>The end result is two lists, one for the months and one for the counts, that are in the correct order.</p>
<p>Happy coding!</p>
https://practicepython.org/blog/2022/02/12/wordleA Python Wordle Clone2022-02-12T00:00:00+00:002022-02-12T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>Written by Michele Pratusevich.</em> When learning how to program, I always recommend having a project or application in mind. For me, it makes it easier to concentrate and learn specific skills and flex the critical thinking muscle. What better project to attempt than the latest game craze, <a href="https://www.powerlanguage.co.uk/wordle/">Wordle</a>? In this post-essay, I’ll take you through the steps required to write your own version of Wordle on the command-line without a GUI in Python.</p>
<!--more-->
<p>If you’d rather, feel free to take this as an exercise / challenge yourself (definitely something like 7 chilis <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> ), then come back here to see how I did it. Alternatively, use this as a guide to code along, as you see my thought process. Note that the way I’ve chosen to structure the code is just one way this could have been implemented. If you go a different route, let’s discuss in the comments. Feel free to skip around!</p>
<ul id="markdown-toc">
<li><a href="#requirements" id="markdown-toc-requirements">Requirements</a> <ul>
<li><a href="#gameplay" id="markdown-toc-gameplay">Gameplay</a></li>
<li><a href="#rules" id="markdown-toc-rules">Rules</a></li>
</ul>
</li>
<li><a href="#basic-design" id="markdown-toc-basic-design">Basic Design</a></li>
<li><a href="#player-guesses" id="markdown-toc-player-guesses">Player Guesses</a></li>
<li><a href="#displaying-guesses" id="markdown-toc-displaying-guesses">Displaying Guesses</a></li>
<li><a href="#generating-the-wordlist" id="markdown-toc-generating-the-wordlist">Generating the Wordlist</a></li>
<li><a href="#putting-it-all-together" id="markdown-toc-putting-it-all-together">Putting it All Together</a></li>
<li><a href="#related-exercises" id="markdown-toc-related-exercises">Related Exercises</a></li>
</ul>
<h2 id="requirements">Requirements</h2>
<p>Before starting any programming project, it is important to make a list of all the features you want it to have. This accomplishes two things: (1) gives you a “stopping point” to know when you’re done, and (2) lets you organize your thoughts to make sure your choices for how to implement cover all your use cases.</p>
<p>In our case, for a Python command-line clone of Wordle, here is our requirements and features list:</p>
<h3 id="gameplay">Gameplay</h3>
<ul>
<li>Game randomly selects a single 5-letter word from a word list to use as the “game word”.</li>
<li>There is a command-line display asking the player to enter guesses.</li>
<li>A guess is only valid if it is the same length as the game word.</li>
<li>All guesses should come from a word list. If the guess is not from the list, tell the player, and don’t accept the word as part of the number of guesses.</li>
<li>The player can enter words either in upper or lower case.</li>
<li>To quit the game early, the player should press CTRL-C. <em>The reasoning behind this choice (rather than, for example, having the player type “quit” or “Q”) is that CTRL-C can never be a guessed word, whereas “QUIT” can be. This means that modifying the game to work with 4-letter words does not break the core game play.</em></li>
<li>The game will keep track of how many guesses the player has done and display that at the end, either when the word is guessed or when the game is quit.</li>
</ul>
<h3 id="rules">Rules</h3>
<ul>
<li>A guessed letter that is correct and in the correct place displays a <code class="language-plaintext highlighter-rouge">*</code>.</li>
<li>A guessed letter that is correct but in the incorrect place displays a <code class="language-plaintext highlighter-rouge">-</code>.</li>
<li>All other guessed letters are returned with a blank <code class="language-plaintext highlighter-rouge">_</code>.</li>
<li>When the game word has two of the same letter, but the guessed word has one of that letter, the letter in the guessed word follows the rules for correct and incorrect placement. For example, if the game word is “STEER” and the guess word is “PLACE” then the “E” in “PLACE” is shown as <code class="language-plaintext highlighter-rouge">-</code>. If the game word is “STEER” and the guess word is “MONEY” then the “E” in “MONEY” is shown as <code class="language-plaintext highlighter-rouge">*</code>.</li>
<li>Correctly guessed letters in the correct place are displayed first.</li>
<li>If the game word has one of a letter, but the guessed word has two, both in the wrong place, only the first letter in the guessed word is displayed as <code class="language-plaintext highlighter-rouge">-</code>.</li>
<li>If the game word has one of a letter, but the guessed word has two, one in the correct place, the correct letter is displayed as <code class="language-plaintext highlighter-rouge">*</code> and the second copy of the letter is unmarked.</li>
</ul>
<h2 id="basic-design">Basic Design</h2>
<p>For any command-line game, the basic program structure is a large infinite <code class="language-plaintext highlighter-rouge">while</code> loop that keeps “playing the game” until an end condition is met. According to our requirements list, the end conditions are:</p>
<ol>
<li>The player guesses the word correctly.</li>
<li>The player exits by pressing CTRL-C.</li>
</ol>
<p>So the first step is to structure our program with this basic scaffold (in a <code class="language-plaintext highlighter-rouge">__main__</code> block). First we tackle the first condition. We don’t deal with selecting the word or processing guesses, so we create two dummy variables (<code class="language-plaintext highlighter-rouge">WORD</code> and <code class="language-plaintext highlighter-rouge">GUESS</code>), set them to specific strings, and continue adding on later.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">WORD</span> <span class="o">=</span> <span class="s">"TESTS"</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">GUESS</span> <span class="o">=</span> <span class="s">"PHONE"</span>
<span class="k">if</span> <span class="n">WORD</span> <span class="o">==</span> <span class="n">GUESS</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You won!"</span><span class="p">)</span>
<span class="k">break</span></code></pre></figure>
<p>Now we can add in the second end condition (exit on CTRL-C). This is slightly more complicated, since in Python the way to catch a CTRL-C press is through a <code class="language-plaintext highlighter-rouge">KeyboardInterrupt</code> exception, so we wrap the existing loop in a <code class="language-plaintext highlighter-rouge">try</code>/<code class="language-plaintext highlighter-rouge">catch</code> to catch the CTRL-C.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">WORD</span> <span class="o">=</span> <span class="s">"TESTS"</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">GUESS</span> <span class="o">=</span> <span class="s">"PHONE"</span>
<span class="k">if</span> <span class="n">WORD</span> <span class="o">==</span> <span class="n">GUESS</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You won!"</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You exited the game."</span><span class="p">)</span></code></pre></figure>
<p>Now that we have the structure of the main loop, we can add in the mechanics for player interaction, namely, taking player guesses.</p>
<h2 id="player-guesses">Player Guesses</h2>
<p>One feature of the game play is that we need some error checking / handling on a player’s guesses. Because this is a functionality that can be independently tested and verified, processing and getting a user guess is a great candidate for putting inside of a function. The heading of this function will look like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">get_user_guess</span><span class="p">(</span><span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Get a user guess input, validate, and return the guess."""</span></code></pre></figure>
<p>The type annotation is natively supported in Python 3, as seen in the <a href="https://docs.python.org/3.9/library/typing.html">official documentation for the <code class="language-plaintext highlighter-rouge">typing</code> library</a>. What our function signature tells us is that the function is going to get the user guess. It takes in two inputs: (1) the length of the expected game word (which is an <code class="language-plaintext highlighter-rouge">int</code>), and (2) the list of available guess words as strings. The function will return a single string, which is the player’s guess. Because we return the string of the guess from this function, all the logic around validating a guess, displaying to the player why the guess is in valid, and asking the user to input a new guess, is contained in this function. Because we are potentially in a situation where we need to ask the user multiple times to enter a guess (if for example they keep entering a 4-letter word when the game word is 5 letters), we use another <code class="language-plaintext highlighter-rouge">while</code> loop here for the structure.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">get_user_guess</span><span class="p">(</span><span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Get a user guess input, validate, and return the guess."""</span>
<span class="c1"># continue looping until you get a valid guess
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Guess: "</span><span class="p">)</span>
<span class="c1"># here we overwrite guess with
</span> <span class="c1"># the filtered guess
</span> <span class="n">error</span><span class="p">,</span> <span class="n">guess</span> <span class="o">=</span> <span class="n">validate</span><span class="p">(</span><span class="n">guess</span><span class="o">=</span><span class="n">guess</span><span class="p">,</span> <span class="n">wordlen</span><span class="o">=</span><span class="n">wordlen</span><span class="p">,</span>
<span class="n">wordlist</span><span class="o">=</span><span class="n">wordlist</span><span class="p">)</span>
<span class="c1"># if there wasn't an error with the guess, we stop asking
</span> <span class="c1"># the user for new guesses
</span> <span class="k">if</span> <span class="n">error</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">break</span>
<span class="c1"># show the input error to the user, as appropriate
</span> <span class="k">print</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
<span class="k">return</span> <span class="n">guess</span></code></pre></figure>
<p>The choice I’ve made here is to abstract the “validation” logic into yet another function. This is because validating a guess is a repeatable action we take on a word that can be independently tested. Let’s write that validation function now:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span>
<span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
<span class="s">"""
Validate a guess from a user.
Return tuple of [None if no error or a string containing
the error message, the guess].
"""</span></code></pre></figure>
<p>Our validation function header will validate a guess according to any validation rules we want. It takes in a guess as a string (any string), the expected length of the game word, and the list of possible game words. What the validation function returns is a tuple containing the error and the guess word. If there is no error, <code class="language-plaintext highlighter-rouge">None</code> is returned for the error. This is again a design choice - some programmers will not return the guess word back, and rely on the fact that if <code class="language-plaintext highlighter-rouge">None</code> is returned for the error, the initial guess word is fine. However, the choice here of returning the guess word is a form of filtering & validation. Because we listed in the requirements that guesses can be entered in uppercase or lower case, we want to standardize all the guesses into uppercase. This means that somewhere we will have to convert the guess into all uppercase letters. What better place to do this than the same function where we are validating our guesses?</p>
<p>The choice for why our <code class="language-plaintext highlighter-rouge">wordlist</code> variable is a <code class="language-plaintext highlighter-rouge">set</code> comes out of this function as well. Inside the validation function, we are checking whether the guess is a member of the valid <code class="language-plaintext highlighter-rouge">wordlist</code> - this operation is cheap to do from a <code class="language-plaintext highlighter-rouge">set</code>, so we choose to take in our <code class="language-plaintext highlighter-rouge">wordlist</code> as a set of strings.</p>
<p>The implementation of the function then looks like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span>
<span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
<span class="s">"""
Validate a guess from a user.
Return tuple of [None if no error or a string containing
the error message, the guess].
"""</span>
<span class="c1"># make sure the guess is all upper case
</span> <span class="n">guess_upper</span> <span class="o">=</span> <span class="n">guess</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span>
<span class="c1"># guesses must be the same as the input word
</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">guess_upper</span><span class="p">)</span> <span class="o">!=</span> <span class="n">wordlen</span><span class="p">:</span>
<span class="k">return</span> <span class="sa">f</span><span class="s">"Guess must be of length </span><span class="si">{</span><span class="n">wordlen</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="c1"># guesses must also be words from the word list
</span> <span class="k">if</span> <span class="n">guess_upper</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">wordlist</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"Guess must be a valid word"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="n">guess_upper</span></code></pre></figure>
<p>Note that all the return statements return a tuple: the first argument is an error string (or <code class="language-plaintext highlighter-rouge">None</code> if we get all the way to the end), and the guess converted into uppercase.</p>
<p>Aside: The syntax in the <code class="language-plaintext highlighter-rouge">return</code> statement with the <code class="language-plaintext highlighter-rouge">f"Guess must be of length {wordlen}"</code> uses <a href="https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals">Python 3’s built-in <em>f-strings</em></a>. They are called <em>f-strings</em> because it stands for “formatted string literals.” It is a special syntax to turn variables easily into strings using the curly braces around the variable name, with lots of formatting options depending on what is desired. The Python documentation has a few examples.</p>
<p>Now that we have a validation function, a user input function, and a main loop, our code so far looks like:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">typing</span>
<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span>
<span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
<span class="s">"""
Validate a guess from a user.
Return tuple of [None if no error or a string containing
the error message, the guess].
"""</span>
<span class="c1"># make sure the guess is all upper case
</span> <span class="n">guess_upper</span> <span class="o">=</span> <span class="n">guess</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span>
<span class="c1"># guesses must be the same as the input word
</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">guess_upper</span><span class="p">)</span> <span class="o">!=</span> <span class="n">wordlen</span><span class="p">:</span>
<span class="k">return</span> <span class="sa">f</span><span class="s">"Guess must be of length </span><span class="si">{</span><span class="n">wordlen</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="c1"># guesses must also be words from the word list
</span> <span class="k">if</span> <span class="n">guess_upper</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">wordlist</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"Guess must be a valid word"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">def</span> <span class="nf">get_user_guess</span><span class="p">(</span><span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Get a user guess input, validate, and return the guess."""</span>
<span class="c1"># continue looping until you get a valid guess
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Guess: "</span><span class="p">)</span>
<span class="c1"># here we overwrite guess with
</span> <span class="c1"># the filtered guess
</span> <span class="n">error</span><span class="p">,</span> <span class="n">guess</span> <span class="o">=</span> <span class="n">validate</span><span class="p">(</span><span class="n">guess</span><span class="o">=</span><span class="n">guess</span><span class="p">,</span> <span class="n">wordlen</span><span class="o">=</span><span class="n">wordlen</span><span class="p">,</span>
<span class="n">wordlist</span><span class="o">=</span><span class="n">wordlist</span><span class="p">)</span>
<span class="c1"># if there wasn't an error with the guess, we stop asking
</span> <span class="c1"># the user for new guesses
</span> <span class="k">if</span> <span class="n">error</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">break</span>
<span class="c1"># show the input error to the user, as appropriate
</span> <span class="k">print</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
<span class="k">return</span> <span class="n">guess</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">WORD</span> <span class="o">=</span> <span class="s">"TESTS"</span>
<span class="n">GAME_WORD_LENGTH</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">WORD</span><span class="p">)</span>
<span class="n">GUESS_WORDLIST</span> <span class="o">=</span> <span class="p">[</span><span class="n">WORD</span><span class="p">,</span> <span class="s">"GAMES"</span><span class="p">,</span> <span class="s">"FRONT"</span><span class="p">,</span> <span class="s">"TILES"</span><span class="p">]</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">GUESS</span> <span class="o">=</span> <span class="n">get_user_guess</span><span class="p">(</span><span class="n">GAME_WORD_LENGTH</span><span class="p">,</span> <span class="n">GUESS_WORDLIST</span><span class="p">)</span>
<span class="k">if</span> <span class="n">WORD</span> <span class="o">==</span> <span class="n">GUESS</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You won!"</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You exited the game."</span><span class="p">)</span></code></pre></figure>
<p>At this point, we have a game where player input is continually read and validated! Next up, displaying information back to the player so the game is actually fun!</p>
<h2 id="displaying-guesses">Displaying Guesses</h2>
<p>Now we get to an interesting coding step: we need to take the guess that we have taken from the user, parse it, and display the information back to the user in a way that makes the game fun. There are two types of information that can be displayed back to the user: guessed letters in the correct place, and guessed letters in the incorrect place. We implement these in that order, to make sure we got it right!</p>
<p>Like always, we start with the function signature:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">compare</span><span class="p">(</span><span class="n">expected</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Compare the guess with the expected word and return the output parse."""</span></code></pre></figure>
<p>What we’ll do is take in the game word (in the <code class="language-plaintext highlighter-rouge">expected</code> variable) as a string, and the (parsed and validated) guess word (in the <code class="language-plaintext highlighter-rouge">guess</code> variable) as a string. This function will do all the character comparison, and output a list of strings denoting the state of each letter in the guess. Per our requirements set up in the previous section, the characters in the output mean the following: (a) <code class="language-plaintext highlighter-rouge">_</code> is a blank - no information is known about this letter; (b) <code class="language-plaintext highlighter-rouge">*</code> is a guessed letter is in the correct place in the game word; (c) <code class="language-plaintext highlighter-rouge">-</code> is a guessed letter that is correct but in the incorrect place in the game word.</p>
<p>We return this parsed list with symbols rather than do the printing directly in this function to separate concerns. If we ever want to change how the display is done in the command-line (for example, add emojis, or add colors, etc.) then we can use the returned parsed list to generate an output.</p>
<p>The first step in writing the function is to set up the output, and we will tackle the easier part of answer parsing: characters in the guessed word that are in the correct place in the game word.</p>
<p>Since this is a tricky function in the Wordle implementation, and the one that most directly affects gameplay, let’s start with a set of test cases that we can call on our function to make sure we have all the cases right!</p>
<table>
<thead>
<tr>
<th>Function call</th>
<th> </th>
<th>Expected Output</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("steer", "stirs")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">* * _ - _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("steer", "floss")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ _ - _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("pains", "stirs")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ * _ *</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("creep", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">- _ _ * -</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("crape", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">- _ _ _ -</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("ennui", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">* * _ _ _</code></td>
</tr>
</tbody>
</table>
<p>These test cases cover a range of outputs and cases that we expect this function to accomplish, both “normal” behavior and a few edge cases that are tricky. What we’re doing here is a miniature version of a software engineering concept called Test Driven Development (TDD). In TDD, the idea is that before you actually write your code, you think about how you are going to test your code, and oftentimes, write the tests first. That way, the verification for “does my code do what it needs to” is already done.</p>
<p>So, let’s begin! First we implement the logic for checking whether guessed characters are in the correct place. This is done (per the rules requirements above) first before the other characters, and those correctly-guessed letters cannot be double-counted. Here is our implementation:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">compare</span><span class="p">(</span><span class="n">expected</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Compare the guess with the expected word and return the output parse."""</span>
<span class="c1"># the output is assumed to be incorrect to start,
</span> <span class="c1"># and as we progress through the checking, update
</span> <span class="c1"># each position in our output list
</span> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s">"_"</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">expected</span><span class="p">)</span>
<span class="c1"># first we check for expected characters in the correct positions
</span> <span class="c1"># and update the output accordingly
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="p">(</span><span class="n">expected_char</span><span class="p">,</span> <span class="n">guess_char</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">guess</span><span class="p">)):</span>
<span class="k">if</span> <span class="n">expected_char</span> <span class="o">==</span> <span class="n">guess_char</span><span class="p">:</span>
<span class="c1"># a correct character in the correct position
</span> <span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"*"</span>
<span class="c1"># return the list of parses
</span> <span class="k">return</span> <span class="n">output</span></code></pre></figure>
<p>At this point if we call this function with our test cases, we will see that we correctly mark the correctly-guessed characters!</p>
<table>
<thead>
<tr>
<th>Function call</th>
<th> </th>
<th>Output so far</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("steer", "stirs")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">* * _ _ _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("steer", "floss")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ _ _ _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("pains", "stirs")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ * _ *</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("creep", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ _ * _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("crape", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ _ _ _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("ennui", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">* * _ _ _</code></td>
</tr>
</tbody>
</table>
<p>Now we move on to the more challenging part: checking for guessed letters that are in the correct place. The way we are going to do this is as follows:</p>
<ul>
<li>First account for all the letters guessed in the correct positions (done above)</li>
<li>Keep track of all the character indices in the game word that have already been “accounted for” by letters from the guessed word. Add all the positions of correctly-guessed letters into this set.</li>
<li>For each guessed character (excluding characters that have already been marked as correctly-positioned guesses), find all the corresponding indices in the game word for that character.</li>
<li>If that position is already accounted for (i.e. is present in the set of accounted-for letters), keep checking for other positions of that character. Once you find a position that has not yet been accounted for, mark the guess with a <code class="language-plaintext highlighter-rouge">-</code>, add that position to the accounted-for set, and move on to the next guessed character.</li>
</ul>
<p>Note that we have to introduce a new structure here to capture the game state: we need to keep track of which characters in the game word have been correctly identified in the game word (whether in the correct or incorrect positions). The reason for this is to take into account the potential for the game word and guess word to both have multiple characters. If there are multiple characters in the guess word, we only count their correct or incorrectness once. That is, if the game word has one “R” but the guess word has two “R”s, then we at most display information back to the user for a single “R” in the guess word (whether that is in the correct or incorrect place). Our test cases listed above cover these gameplay cases.</p>
<p>In this design, we need to write one helper function. Namely, we need to find all the positions of a given letter in the game word. There isn’t any pre-built Python function to do this, so we need to build our own. We base our helper function on the built-in function <a href="https://docs.python.org/3/library/stdtypes.html#str.find"><code class="language-plaintext highlighter-rouge">.find()</code></a> that returns the first index of the desired character in the string. What we want is ALL the positions, so we wrap this function into a loop, and take advantage of the fact that we can specify where in the target word we can search for a character.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">find_all_char_positions</span><span class="p">(</span><span class="n">word</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">char</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>
<span class="s">"""Given a word and a character, find all the indices of that character."""</span>
<span class="n">positions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">word</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
<span class="k">while</span> <span class="n">pos</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="n">positions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">word</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">char</span><span class="p">,</span> <span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">positions</span></code></pre></figure>
<p>We make sure to return a sorted list of positions in the game word as a list of integers, since this is how we expect to use the output of this function for gameplay. The neat thing here is that we do not need to call <code class="language-plaintext highlighter-rouge">sorted()</code> on our output list <code class="language-plaintext highlighter-rouge">positions</code> because the way we call <code class="language-plaintext highlighter-rouge">.find()</code> is guaranteed to return the positions in increasing order.</p>
<p>So with the <code class="language-plaintext highlighter-rouge">find_all_char_positions</code> function built, our code now looks like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">compare</span><span class="p">(</span><span class="n">expected</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Compare the guess with the expected word and return the output parse."""</span>
<span class="c1"># the output is assumed to be incorrect to start,
</span> <span class="c1"># and as we progress through the checking, update
</span> <span class="c1"># each position in our output list
</span> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s">"_"</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">expected</span><span class="p">)</span>
<span class="n">counted_pos</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="c1"># first we check for correct words in the correct positions
</span> <span class="c1"># and update the output accordingly
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="p">(</span><span class="n">expected_char</span><span class="p">,</span> <span class="n">guess_char</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">guess</span><span class="p">)):</span>
<span class="k">if</span> <span class="n">expected_char</span> <span class="o">==</span> <span class="n">guess_char</span><span class="p">:</span>
<span class="c1"># a correct character in the correct position
</span> <span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"*"</span>
<span class="n">counted_pos</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
<span class="c1"># now we check for the remaining letters that are in incorrect
</span> <span class="c1"># positions. in this case, we need to make sure that if the
</span> <span class="c1"># character that this is correct for was already
</span> <span class="c1"># counted as a correct character, we do NOT display
</span> <span class="c1"># this in the double case. e.g. if the correct word
</span> <span class="c1"># is "steer" but we guess "stirs", the second "S"
</span> <span class="c1"># should display "_" and not "-", since the "S" where
</span> <span class="c1"># it belongs was already displayed correctly
</span> <span class="c1"># likewise, if the guess word has two letters in incorrect
</span> <span class="c1"># places, only the first letter is displayed as a "-".
</span> <span class="c1"># e.g. if the guess is "floss" but the game word is "steer"
</span> <span class="c1"># then the output should be "_ _ _ - _"; the second "s" in "floss"
</span> <span class="c1"># is not displayed.
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="n">guess_char</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">guess</span><span class="p">):</span>
<span class="c1"># if the guessed character is in the correct word,
</span> <span class="c1"># we need to check the other conditions. the easiest
</span> <span class="c1"># one is that if we have not already guessed that
</span> <span class="c1"># letter in the correct place. if we have, don't
</span> <span class="c1"># double-count
</span> <span class="k">if</span> <span class="n">guess_char</span> <span class="ow">in</span> <span class="n">expected</span> <span class="ow">and</span> \
<span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">!=</span> <span class="s">"*"</span><span class="p">:</span>
<span class="c1"># first, what are all the positions the guessed
</span> <span class="c1"># character is present in
</span> <span class="n">positions</span> <span class="o">=</span> <span class="n">find_all_char_positions</span><span class="p">(</span><span class="n">word</span><span class="o">=</span><span class="n">expected</span><span class="p">,</span> <span class="n">char</span><span class="o">=</span><span class="n">guess_char</span><span class="p">)</span>
<span class="c1"># have we accounted for all the positions
</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">positions</span><span class="p">:</span>
<span class="c1"># if we have not accounted for the correct
</span> <span class="c1"># position of this letter yet
</span> <span class="k">if</span> <span class="n">pos</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">counted_pos</span><span class="p">:</span>
<span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"-"</span>
<span class="n">counted_pos</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="c1"># we only count the "correct letter" once,
</span> <span class="c1"># so we break out of the "for pos in positions" loop
</span> <span class="k">break</span>
<span class="c1"># return the list of parses
</span> <span class="k">return</span> <span class="n">output</span></code></pre></figure>
<p>We choose a <code class="language-plaintext highlighter-rouge">set</code> as the data structure (in the <code class="language-plaintext highlighter-rouge">counted_pos</code> variable) for keeping track of the counted positions, since the ordering of the positions doesn’t matter, and the most common operation we do on this structure is checking whether the variable <code class="language-plaintext highlighter-rouge">pos</code> is contained in it, which makes a <code class="language-plaintext highlighter-rouge">set</code> an appropriate data structure.</p>
<p>Now we can check against our test cases to confirm we got it right:</p>
<table>
<thead>
<tr>
<th>Function call</th>
<th> </th>
<th>Output</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("steer", "stirs")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">* * _ - _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("steer", "floss")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ _ - _</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("pains", "stirs")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">_ _ * _ *</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("creep", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">- _ _ * -</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("crape", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">- _ _ _ -</code></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">compare("ennui", "enter")</code></td>
<td> </td>
<td><code class="language-plaintext highlighter-rouge">* * _ _ _</code></td>
</tr>
</tbody>
</table>
<p>And there we go! A comparison function for parsing user guesses against a game word. Now we plug this into our main loop for some gameplay!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">typing</span>
<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span>
<span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
<span class="s">"""
Validate a guess from a user.
Return tuple of [None if no error or a string containing
the error message, the guess].
"""</span>
<span class="c1"># make sure the guess is all upper case
</span> <span class="n">guess_upper</span> <span class="o">=</span> <span class="n">guess</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span>
<span class="c1"># guesses must be the same as the input word
</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">guess_upper</span><span class="p">)</span> <span class="o">!=</span> <span class="n">wordlen</span><span class="p">:</span>
<span class="k">return</span> <span class="sa">f</span><span class="s">"Guess must be of length </span><span class="si">{</span><span class="n">wordlen</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="c1"># guesses must also be words from the word list
</span> <span class="k">if</span> <span class="n">guess_upper</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">wordlist</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"Guess must be a valid word"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">def</span> <span class="nf">get_user_guess</span><span class="p">(</span><span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Get a user guess input, validate, and return the guess."""</span>
<span class="c1"># continue looping until you get a valid guess
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Guess: "</span><span class="p">)</span>
<span class="c1"># here we overwrite guess with
</span> <span class="c1"># the filtered guess
</span> <span class="n">error</span><span class="p">,</span> <span class="n">guess</span> <span class="o">=</span> <span class="n">validate</span><span class="p">(</span><span class="n">guess</span><span class="o">=</span><span class="n">guess</span><span class="p">,</span> <span class="n">wordlen</span><span class="o">=</span><span class="n">wordlen</span><span class="p">,</span>
<span class="n">wordlist</span><span class="o">=</span><span class="n">wordlist</span><span class="p">)</span>
<span class="k">if</span> <span class="n">error</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">break</span>
<span class="c1"># show the input error to the user, as appropriate
</span> <span class="k">print</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
<span class="k">return</span> <span class="n">guess</span>
<span class="k">def</span> <span class="nf">find_all_char_positions</span><span class="p">(</span><span class="n">word</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">char</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>
<span class="s">"""Given a word and a character, find all the indices of that character."""</span>
<span class="n">positions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">word</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
<span class="k">while</span> <span class="n">pos</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="n">positions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">word</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">char</span><span class="p">,</span> <span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">positions</span>
<span class="k">def</span> <span class="nf">compare</span><span class="p">(</span><span class="n">expected</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Compare the guess with the expected word and return the output parse."""</span>
<span class="c1"># the output is assumed to be incorrect to start,
</span> <span class="c1"># and as we progress through the checking, update
</span> <span class="c1"># each position in our output list
</span> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s">"_"</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">expected</span><span class="p">)</span>
<span class="n">counted_pos</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="c1"># first we check for correct words in the correct positions
</span> <span class="c1"># and update the output accordingly
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="p">(</span><span class="n">expected_char</span><span class="p">,</span> <span class="n">guess_char</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">guess</span><span class="p">)):</span>
<span class="k">if</span> <span class="n">expected_char</span> <span class="o">==</span> <span class="n">guess_char</span><span class="p">:</span>
<span class="c1"># a correct character in the correct position
</span> <span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"*"</span>
<span class="n">counted_pos</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
<span class="c1"># now we check for the remaining letters that are in incorrect
</span> <span class="c1"># positions. in this case, we need to make sure that if the
</span> <span class="c1"># character that this is correct for was already
</span> <span class="c1"># counted as a correct character, we do NOT display
</span> <span class="c1"># this in the double case. e.g. if the correct word
</span> <span class="c1"># is "steer" but we guess "stirs", the second "S"
</span> <span class="c1"># should display "_" and not "-", since the "S" where
</span> <span class="c1"># it belongs was already displayed correctly
</span> <span class="c1"># likewise, if the guess word has two letters in incorrect
</span> <span class="c1"># places, only the first letter is displayed as a "-".
</span> <span class="c1"># e.g. if the guess is "floss" but the game word is "steer"
</span> <span class="c1"># then the output should be "_ _ _ - _"; the second "s" in "floss"
</span> <span class="c1"># is not displayed.
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="n">guess_char</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">guess</span><span class="p">):</span>
<span class="c1"># if the guessed character is in the correct word,
</span> <span class="c1"># we need to check the other conditions. the easiest
</span> <span class="c1"># one is that if we have not already guessed that
</span> <span class="c1"># letter in the correct place. if we have, don't
</span> <span class="c1"># double-count
</span> <span class="k">if</span> <span class="n">guess_char</span> <span class="ow">in</span> <span class="n">expected</span> <span class="ow">and</span> \
<span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">!=</span> <span class="s">"*"</span><span class="p">:</span>
<span class="c1"># first, what are all the positions the guessed
</span> <span class="c1"># character is present in
</span> <span class="n">positions</span> <span class="o">=</span> <span class="n">find_all_char_positions</span><span class="p">(</span><span class="n">word</span><span class="o">=</span><span class="n">expected</span><span class="p">,</span> <span class="n">char</span><span class="o">=</span><span class="n">guess_char</span><span class="p">)</span>
<span class="c1"># have we accounted for all the positions
</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">positions</span><span class="p">:</span>
<span class="c1"># if we have not accounted for the correct
</span> <span class="c1"># position of this letter yet
</span> <span class="k">if</span> <span class="n">pos</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">counted_pos</span><span class="p">:</span>
<span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"-"</span>
<span class="n">counted_pos</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="c1"># we only count the "correct letter" once,
</span> <span class="c1"># so we break out of the "for pos in positions" loop
</span> <span class="k">break</span>
<span class="c1"># return the list of parses
</span> <span class="k">return</span> <span class="n">output</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">WORD</span> <span class="o">=</span> <span class="s">"TESTS"</span>
<span class="n">GAME_WORD_LENGTH</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">WORD</span><span class="p">)</span>
<span class="n">GUESS_WORDLIST</span> <span class="o">=</span> <span class="p">[</span><span class="n">WORD</span><span class="p">,</span> <span class="s">"GAMES"</span><span class="p">,</span> <span class="s">"FRONT"</span><span class="p">,</span> <span class="s">"TILES"</span><span class="p">]</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1"># get the user to guess something
</span> <span class="n">GUESS</span> <span class="o">=</span> <span class="n">get_user_guess</span><span class="p">(</span>
<span class="n">wordlen</span><span class="o">=</span><span class="n">GAME_WORD_LENGTH</span><span class="p">,</span> <span class="n">wordlist</span><span class="o">=</span><span class="n">GUESSWORD_WORDLIST</span><span class="p">)</span>
<span class="c1"># display the guess when compared against the game word
</span> <span class="n">result</span> <span class="o">=</span> <span class="n">compare</span><span class="p">(</span><span class="n">expected</span><span class="o">=</span><span class="n">WORD</span><span class="p">,</span> <span class="n">guess</span><span class="o">=</span><span class="n">GUESS</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
<span class="k">if</span> <span class="n">WORD</span> <span class="o">==</span> <span class="n">GUESS</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You won!"</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You exited the game."</span><span class="p">)</span></code></pre></figure>
<p>And now we have a playable game!</p>
<h2 id="generating-the-wordlist">Generating the Wordlist</h2>
<p>Of course, one “trick” we did with our implementation so far is hard-code the game word. This makes for a pretty boring game, so as the next step is to generate some word lists that are more fun!</p>
<p>There is “right way” to generate a word list. Because of a previous exercise on this blog, I had a local copy of <a href="https://www.wordgamedictionary.com/sowpods/">SOWPODS</a>, the official Scrabble word list, locally. However, as you know of Scrabble words, some are a bit obscure and not very fun for gameplay. Besides, SOWPODS has words of many lengths, whereas in our version of Wordle we wanted to limit only to 5-letter words.</p>
<p>The additional detail about word lists in Wordle is that there are actually <em>two</em> word lists. One word list for game words (which has fewer words, and contains more “common” words), and a separate word list for validating guesses, which contains the game word list and a bunch of other more “obscure” words. I don’t know for sure how the original implementor of Wordle generated these lists, but I have to assume some amount of hand-curation was done.</p>
<p>We on the other hand don’t need to hand-curate our list (unless you want to for your own implementation). Instead, we look at the page source for Wordle and extract the lists from that code. I won’t go into exactly how I did that here, since I didn’t use Python for it! We save these as two separate word lists (<code class="language-plaintext highlighter-rouge">gamewords.txt</code> and <code class="language-plaintext highlighter-rouge">guesswords.txt</code>) that we can load into our game. One helper function we will write (since it will be used twice, once for each list of words), is a <code class="language-plaintext highlighter-rouge">create_wordlist()</code> helper function that loads the word lists into a list and makes sure all the words are upper case.</p>
<p>We actually implement this as two functions: one for filtering/modifying words, and one for ingesting the word list in the first place. This is because if we ever want to expand the word lists to contain words of multiple lengths, we don’t need to maintain separate word lists for all the lengths; we can simply put them in one list, and filter the random game/guess words in real time during game play.</p>
<p>First we implement a <code class="language-plaintext highlighter-rouge">filter_word()</code> function that takes in a word and any filtering criteria. It returns back the word modified (in our case converted to upper case). If we decide to add new functionality into our Wordle implementation (for example, limiting words to only start with “T” or something else), then that functionality would be added into this function.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">filter_word</span><span class="p">(</span><span class="n">word</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">length</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Filter a word to add it to the wordlist."""</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">.</span><span class="n">strip</span><span class="p">())</span> <span class="o">==</span> <span class="n">length</span><span class="p">:</span>
<span class="c1"># make sure all the words in our wordlist
</span> <span class="c1"># are stripped of whitespace, and all upper case,
</span> <span class="c1"># for consistency in checking
</span> <span class="k">return</span> <span class="n">word</span><span class="p">.</span><span class="n">strip</span><span class="p">().</span><span class="n">upper</span><span class="p">()</span>
<span class="k">return</span> <span class="bp">None</span></code></pre></figure>
<p>Now when we implement our <code class="language-plaintext highlighter-rouge">create_wordlist()</code> function, we can make use of a Python built-in function called <a href="https://docs.python.org/3/library/functions.html#map"><code class="language-plaintext highlighter-rouge">map</code></a>. I have not yet written an exercise specifically about this function, so I’ll briefly touch on it here. The purpose of <code class="language-plaintext highlighter-rouge">map</code> is to apply the same function on any iterable (list, dictionary, set) and return a new version of that iterable with the function applied. In our case this works out perfectly: what we want to do is take in a list of words that we loaded from a text file, and we want to make them all uppercase. More specifically, we want to apply our <code class="language-plaintext highlighter-rouge">filter_word</code> function to each element of the word list.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">create_wordlist</span><span class="p">(</span><span class="n">fname</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">length</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Load and create a wordlist from a filename."""</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">lines</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">word</span><span class="p">:</span> <span class="n">filter_word</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="n">length</span><span class="p">),</span> <span class="n">lines</span><span class="p">))</span></code></pre></figure>
<p>The end result is that when we call the <code class="language-plaintext highlighter-rouge">create_wordlist()</code> function on our word list, it converts all the words properly to upper case and filters out any undesirable words.</p>
<p>At this point we are ready to put it all together!</p>
<h2 id="putting-it-all-together">Putting it All Together</h2>
<p>Now we just add a few bells and whistles to the text of what the user sees during gameplay (the number of guesses taken, for example), and voila! We have a full Wordle implementation in Python!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="s">"""An implementation of Wordle in Python."""</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">typing</span>
<span class="n">GAMEWORD_LIST_FNAME</span> <span class="o">=</span> <span class="s">"gamewords.txt"</span>
<span class="n">GUESSWORD_LIST_FNAME</span> <span class="o">=</span> <span class="s">"guesswords.txt"</span>
<span class="k">def</span> <span class="nf">filter_word</span><span class="p">(</span><span class="n">word</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">length</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Filter a word to add it to the wordlist."""</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">.</span><span class="n">strip</span><span class="p">())</span> <span class="o">==</span> <span class="n">length</span><span class="p">:</span>
<span class="c1"># make sure all the words in our wordlist
</span> <span class="c1"># are stripped of whitespace, and all upper case,
</span> <span class="c1"># for consistency in checking
</span> <span class="k">return</span> <span class="n">word</span><span class="p">.</span><span class="n">strip</span><span class="p">().</span><span class="n">upper</span><span class="p">()</span>
<span class="k">return</span> <span class="bp">None</span>
<span class="k">def</span> <span class="nf">create_wordlist</span><span class="p">(</span><span class="n">fname</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">length</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Load and create a wordlist from a filename."""</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">lines</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">word</span><span class="p">:</span> <span class="n">filter_word</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="n">length</span><span class="p">),</span> <span class="n">lines</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span>
<span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">Tuple</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
<span class="s">"""
Validate a guess from a user.
Return tuple of [None if no error or a string containing
the error message, the guess].
"""</span>
<span class="c1"># make sure the guess is all upper case
</span> <span class="n">guess_upper</span> <span class="o">=</span> <span class="n">guess</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span>
<span class="c1"># guesses must be the same as the input word
</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">guess_upper</span><span class="p">)</span> <span class="o">!=</span> <span class="n">wordlen</span><span class="p">:</span>
<span class="k">return</span> <span class="sa">f</span><span class="s">"Guess must be of length </span><span class="si">{</span><span class="n">wordlen</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="c1"># guesses must also be words from the word list
</span> <span class="k">if</span> <span class="n">guess_upper</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">wordlist</span><span class="p">:</span>
<span class="k">return</span> <span class="s">"Guess must be a valid word"</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">return</span> <span class="bp">None</span><span class="p">,</span> <span class="n">guess_upper</span>
<span class="k">def</span> <span class="nf">get_user_guess</span><span class="p">(</span><span class="n">wordlen</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">wordlist</span><span class="p">:</span> <span class="n">typing</span><span class="p">.</span><span class="n">Set</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="s">"""Get a user guess input, validate, and return the guess."""</span>
<span class="c1"># continue looping until you get a valid guess
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Guess: "</span><span class="p">)</span>
<span class="c1"># here we overwrite guess with
</span> <span class="c1"># the filtered guess
</span> <span class="n">error</span><span class="p">,</span> <span class="n">guess</span> <span class="o">=</span> <span class="n">validate</span><span class="p">(</span><span class="n">guess</span><span class="o">=</span><span class="n">guess</span><span class="p">,</span> <span class="n">wordlen</span><span class="o">=</span><span class="n">wordlen</span><span class="p">,</span>
<span class="n">wordlist</span><span class="o">=</span><span class="n">wordlist</span><span class="p">)</span>
<span class="k">if</span> <span class="n">error</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">break</span>
<span class="c1"># show the input error to the user, as appropriate
</span> <span class="k">print</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>
<span class="k">return</span> <span class="n">guess</span>
<span class="k">def</span> <span class="nf">find_all_char_positions</span><span class="p">(</span><span class="n">word</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">char</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>
<span class="s">"""Given a word and a character, find all the indices of that character."""</span>
<span class="n">positions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">word</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
<span class="k">while</span> <span class="n">pos</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="n">positions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">word</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">char</span><span class="p">,</span> <span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">positions</span>
<span class="c1"># test cases for find_all_char_positions
# find_all_char_positions("steer", "e") => [2, 3]
# find_all_char_positions("steer", "t") => [1]
# find_all_char_positions("steer", "q") => []
</span>
<span class="k">def</span> <span class="nf">compare</span><span class="p">(</span><span class="n">expected</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">guess</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="n">typing</span><span class="p">.</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
<span class="s">"""Compare the guess with the expected word and return the output parse."""</span>
<span class="c1"># the output is assumed to be incorrect to start,
</span> <span class="c1"># and as we progress through the checking, update
</span> <span class="c1"># each position in our output list
</span> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s">"_"</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">expected</span><span class="p">)</span>
<span class="n">counted_pos</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="c1"># first we check for correct words in the correct positions
</span> <span class="c1"># and update the output accordingly
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="p">(</span><span class="n">expected_char</span><span class="p">,</span> <span class="n">guess_char</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">guess</span><span class="p">)):</span>
<span class="k">if</span> <span class="n">expected_char</span> <span class="o">==</span> <span class="n">guess_char</span><span class="p">:</span>
<span class="c1"># a correct character in the correct position
</span> <span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"*"</span>
<span class="n">counted_pos</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
<span class="c1"># now we check for the remaining letters that are in incorrect
</span> <span class="c1"># positions. in this case, we need to make sure that if the
</span> <span class="c1"># character that this is correct for was already
</span> <span class="c1"># counted as a correct character, we do NOT display
</span> <span class="c1"># this in the double case. e.g. if the correct word
</span> <span class="c1"># is "steer" but we guess "stirs", the second "S"
</span> <span class="c1"># should display "_" and not "-", since the "S" where
</span> <span class="c1"># it belongs was already displayed correctly
</span> <span class="c1"># likewise, if the guess word has two letters in incorrect
</span> <span class="c1"># places, only the first letter is displayed as a "-".
</span> <span class="c1"># e.g. if the guess is "floss" but the game word is "steer"
</span> <span class="c1"># then the output should be "_ _ _ - _"; the second "s" in "floss"
</span> <span class="c1"># is not displayed.
</span> <span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="n">guess_char</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">guess</span><span class="p">):</span>
<span class="c1"># if the guessed character is in the correct word,
</span> <span class="c1"># we need to check the other conditions. the easiest
</span> <span class="c1"># one is that if we have not already guessed that
</span> <span class="c1"># letter in the correct place. if we have, don't
</span> <span class="c1"># double-count
</span> <span class="k">if</span> <span class="n">guess_char</span> <span class="ow">in</span> <span class="n">expected</span> <span class="ow">and</span> \
<span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">!=</span> <span class="s">"*"</span><span class="p">:</span>
<span class="c1"># first, what are all the positions the guessed
</span> <span class="c1"># character is present in
</span> <span class="n">positions</span> <span class="o">=</span> <span class="n">find_all_char_positions</span><span class="p">(</span><span class="n">word</span><span class="o">=</span><span class="n">expected</span><span class="p">,</span> <span class="n">char</span><span class="o">=</span><span class="n">guess_char</span><span class="p">)</span>
<span class="c1"># have we accounted for all the positions
</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="n">positions</span><span class="p">:</span>
<span class="c1"># if we have not accounted for the correct
</span> <span class="c1"># position of this letter yet
</span> <span class="k">if</span> <span class="n">pos</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">counted_pos</span><span class="p">:</span>
<span class="n">output</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="s">"-"</span>
<span class="n">counted_pos</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
<span class="c1"># we only count the "correct letter" once,
</span> <span class="c1"># so we break out of the "for pos in positions" loop
</span> <span class="k">break</span>
<span class="c1"># return the list of parses
</span> <span class="k">return</span> <span class="n">output</span>
<span class="c1"># test cases for comparing
# compare("steer", "stirs") -> "* * _ - _"
# compare("steer", "floss") -> "_ _ _ - _"
# compare("pains", "stirs") -> "_ _ * _ *"
# compare("creep", "enter") -> "- _ _ * -"
# compare("crape", "enter") -> "- _ _ _ -"
# compare("ennui", "enter") -> "* * _ _ _"
</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="c1"># the game word is 5 letters
</span> <span class="n">WORDLEN</span> <span class="o">=</span> <span class="mi">5</span>
<span class="c1"># load the wordlist that we will select words from
</span> <span class="c1"># for the wordle game
</span> <span class="n">GAMEWORD_WORDLIST</span> <span class="o">=</span> <span class="n">create_wordlist</span><span class="p">(</span>
<span class="n">GAMEWORD_LIST_FNAME</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="n">WORDLEN</span><span class="p">)</span>
<span class="c1"># load the wordlist for the guesses
</span> <span class="c1"># this needs to be a set, since we pass this into the get_user_guess()
</span> <span class="c1"># function which expects a set
</span> <span class="n">GUESSWORD_WORDLIST</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">create_wordlist</span><span class="p">(</span>
<span class="n">GUESSWORD_LIST_FNAME</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="n">WORDLEN</span><span class="p">))</span>
<span class="c1"># select a random word to start with
</span> <span class="n">WORD</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">choice</span><span class="p">(</span><span class="n">GAMEWORD_WORDLIST</span><span class="p">)</span>
<span class="n">GAME_WORD_LENGTH</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">WORD</span><span class="p">)</span>
<span class="c1"># keep track of some game state
</span> <span class="n">NUM_GUESSES</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c1"># print the game instructions to the user
</span> <span class="k">print</span><span class="p">(</span><span class="s">"""
Guess words one at a time to guess the game word.
A * character means a letter was guessed correctly
in the correct position.
A - character means a letter was guessed correctly,
but in the incorrect position.
To quit, press CTRL-C.
"""</span><span class="p">)</span>
<span class="c1"># start of the user name interaction
</span> <span class="k">print</span><span class="p">(</span><span class="s">"_ "</span> <span class="o">*</span> <span class="n">GAME_WORD_LENGTH</span><span class="p">)</span>
<span class="c1"># we use a continuous loop, since there could be a number
</span> <span class="c1"># of different exit conditions from the game if we want
</span> <span class="c1"># to spruce it up.
</span> <span class="k">try</span><span class="p">:</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1"># get the user to guess something
</span> <span class="n">GUESS</span> <span class="o">=</span> <span class="n">get_user_guess</span><span class="p">(</span>
<span class="n">wordlen</span><span class="o">=</span><span class="n">GAME_WORD_LENGTH</span><span class="p">,</span> <span class="n">wordlist</span><span class="o">=</span><span class="n">GUESSWORD_WORDLIST</span><span class="p">)</span>
<span class="n">NUM_GUESSES</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="c1"># display the guess when compared against the game word
</span> <span class="n">result</span> <span class="o">=</span> <span class="n">compare</span><span class="p">(</span><span class="n">expected</span><span class="o">=</span><span class="n">WORD</span><span class="p">,</span> <span class="n">guess</span><span class="o">=</span><span class="n">GUESS</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">" "</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
<span class="k">if</span> <span class="n">WORD</span> <span class="o">==</span> <span class="n">GUESS</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"You won! It took you </span><span class="si">{</span><span class="n">NUM_GUESSES</span><span class="si">}</span><span class="s"> guesses."</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"""
You quit - the correct answer was </span><span class="si">{</span><span class="n">WORD</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s">
and you took </span><span class="si">{</span><span class="n">NUM_GUESSES</span><span class="si">}</span><span class="s"> guesses
"""</span><span class="p">)</span></code></pre></figure>
<p>When you run this code through the terminal, a sample gameplay looks like this:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">[mprat@europa] $ python wordle.py
Guess words one at a time to guess the game word.
A * character means a letter was guessed correctly
in the correct position.
A - character means a letter was guessed correctly,
but in the incorrect position.
To quit, press CTRL-C.
_ _ _ _ _
Guess: stare
_ _ _ - -
Guess: reign
- - _ _ _
Guess: erode
- - _ _ -
Guess: never
_ - _ * *
Guess: cheer
* * * * *
You won! It took you 5 guesses.</code></pre></figure>
<h2 id="related-exercises">Related Exercises</h2>
<p>This website contains a few exercises that are relevant to the skills required to code up Wordle. Here are a few, but feel free to get started anywhere!</p>
<ul>
<li><a href="/exercise/2014/01/29/01-character-input.html">using <code class="language-plaintext highlighter-rouge">input</code> to get info from the user</a></li>
<li><a href="/exercise/2014/12/06/22-read-from-file.html">reading from a file</a></li>
<li><a href="/exercise/2014/04/02/09-guessing-game-one.html">a simpler guessing game</a></li>
<li><a href="/exercise/2015/11/01/25-guessing-game-two.html">another kind of guessing game</a></li>
<li><a href="/exercise/2014/07/05/18-cows-and-bulls.html">cows and bulls</a></li>
<li>the Hangman series: <a href="/exercise/2016/09/24/30-pick-word.html">picking a word from a list</a>, <a href="/solution/2017/01/08/31-guess-letters-solutions.html">guessing letters</a>, and <a href="/exercise/2017/01/10/32-hangman.html">putting it all together</a></li>
</ul>
https://practicepython.org/exercise/2017/04/02/36-birthday-plots36 Birthday Plots2017-04-02T00:00:00+00:002017-04-02T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In the <a href="/exercise/2017/02/28/35-birthday-months.html">previous exercise</a> we counted how many birthdays there are in each month in our dictionary of birthdays.</p>
<p>In this exercise, use the <a href="http://bokeh.pydata.org/en/latest/">bokeh</a> Python library to plot a histogram of which months the scientists have birthdays in! Because it would take a long time for you to input the months of various scientists, you can use <a href="/assets/scientist_birthdays.json">my scientist birthday JSON file</a>. Just parse out the months (if you don’t know how, I suggest looking at the <a href="/exercise/2017/02/28/35-birthday-months.html">previous exercise</a> or <a href="/solution/2017/03/19/35-birthday-months-solutions.html">its solution</a>) and draw your histogram.</p>
<p>If you are using a purely web-based interface for coding, this exercise won’t work for you, since it requires installing the <code class="language-plaintext highlighter-rouge">bokeh</code> Python package. Now might be a good time to <a href="/blog/2017/03/24/install-python.html">install Python on your own computer</a>.</p>
<h1 id="discussion">Discussion</h1>
<p>Today’s topic is going to be about the <a href="http://bokeh.pydata.org/en/latest/">bokeh</a> plotting library. We create plots and charts to display and communicate information from data, and it would be great to do that directly from Python. Sometimes it is really nice to write code or algorithms from scratch to learn and practice, and sometimes, someone has already written the code so well that you should use theirs. Bokeh is one of these libraries - it is library specifically with functions for making plots, charts, and graphs. It is based on the famous <a href="https://d3js.org/">D3.js</a> library originally developed at the <em>New York Times</em> for their visualizations, which has been used for many years to programmatically create visually appealing data visualizations.</p>
<h2 id="when-to-make-plots">When to make plots</h2>
<p>We use plots to convey information. From this histogram:</p>
<p><img src="/assets/imgs/united-states-government-spending.png" alt="US Government spending histogram" /></p>
<p>You can immediately see that the US government spending has been steadily increasing, reaching a peak in January 2017.</p>
<p>So learning how to make plots will help you become better at displaying and communicating information, both to yourself and to others.</p>
<h2 id="plotting-libraries-in-python">Plotting libraries in Python</h2>
<p>If you are looking for a plotting library in Python, you have two main options: <a href="http://matplotlib.org/">matplotlib</a> and <a href="http://bokeh.pydata.org/en/latest/">bokeh</a>. Today I want to discuss bokeh, because I think it will become more popular in years to come.</p>
<p>Many Python developers (and especially data scientists and researchers) will tell you that the most commonly used plotting library in Python is <a href="http://matplotlib.org/">matplotlib</a>. I myself was a matplotlib user for many years - the integrations with Python data libraries are great, and migrating from the MATLAB plotting environment to matplotlib is easy. But a friend introduced me to bokeh and I was hooked ever since. Because it is based on D3.js, the visualizations look smooth and professional.</p>
<p>There is no one “best” plotting library - you should use whichever one feels and looks better for you. But for the rest of this post, I’ll talk about how to use bokeh to make a basic plot.</p>
<h2 id="installing-bokeh">Installing bokeh</h2>
<p>To use bokeh, we first have to install it. Unlike something like <a href="https://docs.python.org/3/library/json.html"><code class="language-plaintext highlighter-rouge">json</code></a> or <a href="https://docs.python.org/3/library/collections.html#collections.Counter"><code class="language-plaintext highlighter-rouge">Counter</code></a> from previous exercises, bokeh does not come installed with Python.</p>
<p>If you are using the <a href="https://www.continuum.io/downloads">Anaconda Python</a> distribution (which you should, if you are on Windows!) then you can install bokeh by typing</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">conda <span class="nb">install </span>bokeh</code></pre></figure>
<p>in the Windows command prompt or the bash shell.</p>
<p>On OSX or GNU / Linux, just type</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">pip3 <span class="nb">install </span>bokeh</code></pre></figure>
<p>(If you have are using Python 2, you should do <code class="language-plaintext highlighter-rouge">pip install bokeh</code>.)</p>
<h2 id="using-bokeh">Using bokeh</h2>
<p>The basic idea of any plotting package is simple:</p>
<ol>
<li>Load the data</li>
<li>Display the data</li>
</ol>
<p>So the first thing you have to do is prepare some data. Usually, when you are plotting data you have two axes, or groups of data, an x-axis (or horizontal axis) and a y-axis (or vertical axis). The <code class="language-plaintext highlighter-rouge">x</code> variable is your input (independent) variable and the <code class="language-plaintext highlighter-rouge">y</code> variable is your output (dependent) variable.</p>
<p>For use in bokeh, your data should be loaded into two separate lists, one for the x-axis and one for the y-axis. The basic format of a bokeh (in this case histogram) looks like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># need to import at least 3 things to make your
# bokeh plots work
</span><span class="kn">from</span> <span class="nn">bokeh.plotting</span> <span class="kn">import</span> <span class="n">figure</span><span class="p">,</span> <span class="n">show</span><span class="p">,</span> <span class="n">output_file</span>
<span class="c1"># we specify an HTML file where the output will go
</span><span class="n">output_file</span><span class="p">(</span><span class="s">"plot.html"</span><span class="p">)</span>
<span class="c1"># load our x and y data
</span><span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">]</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span>
<span class="c1"># create a figure
</span><span class="n">p</span> <span class="o">=</span> <span class="n">figure</span><span class="p">()</span>
<span class="c1"># create a histogram
</span><span class="n">p</span><span class="p">.</span><span class="n">vbar</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="n">y</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
<span class="c1"># render (show) the plot
</span><span class="n">show</span><span class="p">(</span><span class="n">p</span><span class="p">)</span></code></pre></figure>
<p>The way bokeh outputs plots is really cool: when you run a piece of bokeh code, it outputs the result into an HTML file that you can then save and display in a web browser on it’s own. After you run this segment on top, it will automatically open a web browser and show you a plot.</p>
<p>One awesome feature of Bokeh is that it gives you a toolbar you can use to play with the graph - moving it around, zooming out, saving it, etc. Plus, you can put it directly into am HTML page!</p>
<p>It will look something like this:</p>
<div class="bk-root" id="93fbfba1-3111-41d0-9061-f1167ce0c394" data-root-id="1621"></div>
<script type="application/json" id="1801">
{"b71c6e00-8afb-4a00-8337-5c3d75677a83":{"defs":[],"roots":{"references":[{"attributes":{},"id":"1622","type":"DataRange1d"},{"attributes":{"coordinates":null,"formatter":{"id":"1664"},"group":null,"major_label_policy":{"id":"1665"},"ticker":{"id":"1631"}},"id":"1630","type":"LinearAxis"},{"attributes":{"coordinates":null,"group":null},"id":"1658","type":"Title"},{"attributes":{},"id":"1638","type":"PanTool"},{"attributes":{},"id":"1639","type":"WheelZoomTool"},{"attributes":{},"id":"1664","type":"BasicTickFormatter"},{"attributes":{"source":{"id":"1652"}},"id":"1657","type":"CDSView"},{"attributes":{"coordinates":null,"data_source":{"id":"1652"},"glyph":{"id":"1653"},"group":null,"hover_glyph":null,"muted_glyph":{"id":"1655"},"nonselection_glyph":{"id":"1654"},"view":{"id":"1657"}},"id":"1656","type":"GlyphRenderer"},{"attributes":{"axis":{"id":"1630"},"coordinates":null,"group":null,"ticker":null},"id":"1633","type":"Grid"},{"attributes":{},"id":"1667","type":"Selection"},{"attributes":{},"id":"1666","type":"UnionRenderers"},{"attributes":{"below":[{"id":"1630"}],"center":[{"id":"1633"},{"id":"1637"}],"left":[{"id":"1634"}],"renderers":[{"id":"1656"}],"title":{"id":"1658"},"toolbar":{"id":"1645"},"x_range":{"id":"1622"},"x_scale":{"id":"1626"},"y_range":{"id":"1624"},"y_scale":{"id":"1628"}},"id":"1621","subtype":"Figure","type":"Plot"},{"attributes":{},"id":"1631","type":"BasicTicker"},{"attributes":{"overlay":{"id":"1644"}},"id":"1640","type":"BoxZoomTool"},{"attributes":{},"id":"1635","type":"BasicTicker"},{"attributes":{},"id":"1642","type":"ResetTool"},{"attributes":{},"id":"1641","type":"SaveTool"},{"attributes":{},"id":"1643","type":"HelpTool"},{"attributes":{"fill_color":{"value":"#1f77b4"},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"width":{"value":0.5},"x":{"field":"x"}},"id":"1653","type":"VBar"},{"attributes":{},"id":"1624","type":"DataRange1d"},{"attributes":{"data":{"top":[4,5,6],"x":[10,20,30]},"selected":{"id":"1667"},"selection_policy":{"id":"1666"}},"id":"1652","type":"ColumnDataSource"},{"attributes":{},"id":"1628","type":"LinearScale"},{"attributes":{"tools":[{"id":"1638"},{"id":"1639"},{"id":"1640"},{"id":"1641"},{"id":"1642"},{"id":"1643"}]},"id":"1645","type":"Toolbar"},{"attributes":{"bottom_units":"screen","coordinates":null,"fill_alpha":0.5,"fill_color":"lightgrey","group":null,"left_units":"screen","level":"overlay","line_alpha":1.0,"line_color":"black","line_dash":[4,4],"line_width":2,"right_units":"screen","syncable":false,"top_units":"screen"},"id":"1644","type":"BoxAnnotation"},{"attributes":{"coordinates":null,"formatter":{"id":"1661"},"group":null,"major_label_policy":{"id":"1662"},"ticker":{"id":"1635"}},"id":"1634","type":"LinearAxis"},{"attributes":{},"id":"1665","type":"AllLabels"},{"attributes":{},"id":"1626","type":"LinearScale"},{"attributes":{},"id":"1662","type":"AllLabels"},{"attributes":{},"id":"1661","type":"BasicTickFormatter"},{"attributes":{"fill_alpha":{"value":0.2},"fill_color":{"value":"#1f77b4"},"hatch_alpha":{"value":0.2},"line_alpha":{"value":0.2},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"width":{"value":0.5},"x":{"field":"x"}},"id":"1655","type":"VBar"},{"attributes":{"axis":{"id":"1634"},"coordinates":null,"dimension":1,"group":null,"ticker":null},"id":"1637","type":"Grid"},{"attributes":{"fill_alpha":{"value":0.1},"fill_color":{"value":"#1f77b4"},"hatch_alpha":{"value":0.1},"line_alpha":{"value":0.1},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"width":{"value":0.5},"x":{"field":"x"}},"id":"1654","type":"VBar"}],"root_ids":["1621"]},"title":"Bokeh Application","version":"2.4.2"}}
</script>
<script type="text/javascript">
(function() {
const fn = function() {
Bokeh.safely(function() {
(function(root) {
function embed_document(root) {
const docs_json = document.getElementById('1801').textContent;
const render_items = [{"docid":"b71c6e00-8afb-4a00-8337-5c3d75677a83","root_ids":["1621"],"roots":{"1621":"93fbfba1-3111-41d0-9061-f1167ce0c394"}}];
root.Bokeh.embed.embed_items(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
});
};
if (document.readyState != "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
})();
</script>
<p>The example above works when <code class="language-plaintext highlighter-rouge">x</code> is a numerical value. But, in the exercise, we are dealing with months, which is called a “categorical” variable (i.e. it belongs to a category, and is not continuous). To make sure bokeh draws the axis correctly, you need to specify a special call to <code class="language-plaintext highlighter-rouge">figure()</code> to pass an <code class="language-plaintext highlighter-rouge">x_range</code>, like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">bokeh.plotting</span> <span class="kn">import</span> <span class="n">figure</span><span class="p">,</span> <span class="n">show</span><span class="p">,</span> <span class="n">output_file</span>
<span class="n">output_file</span><span class="p">(</span><span class="s">"plot.html"</span><span class="p">)</span>
<span class="n">x_categories</span> <span class="o">=</span> <span class="p">[</span><span class="s">"a"</span><span class="p">,</span> <span class="s">"b"</span><span class="p">,</span> <span class="s">"c"</span><span class="p">,</span> <span class="s">"d"</span><span class="p">,</span> <span class="s">"e"</span><span class="p">]</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="s">"a"</span><span class="p">,</span> <span class="s">"d"</span><span class="p">,</span> <span class="s">"e"</span><span class="p">]</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">figure</span><span class="p">(</span><span class="n">x_range</span><span class="o">=</span><span class="n">x_categories</span><span class="p">)</span>
<span class="n">p</span><span class="p">.</span><span class="n">vbar</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">x</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="n">y</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
<span class="n">show</span><span class="p">(</span><span class="n">p</span><span class="p">)</span></code></pre></figure>
<p>Here’s what this one looks like:</p>
<div class="bk-root" id="1cc70986-5765-4f3c-8dab-ebcc901298e2" data-root-id="1802"></div>
<script type="application/json" id="1981">
{"883b6c59-c219-42d0-825d-9acf30299e7b":{"defs":[],"roots":{"references":[{"attributes":{"coordinates":null,"formatter":{"id":"1841"},"group":null,"major_label_policy":{"id":"1842"},"ticker":{"id":"1815"}},"id":"1814","type":"LinearAxis"},{"attributes":{"axis":{"id":"1814"},"coordinates":null,"dimension":1,"group":null,"ticker":null},"id":"1817","type":"Grid"},{"attributes":{"fill_alpha":{"value":0.1},"fill_color":{"value":"#1f77b4"},"hatch_alpha":{"value":0.1},"line_alpha":{"value":0.1},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"width":{"value":0.5},"x":{"field":"x"}},"id":"1834","type":"VBar"},{"attributes":{},"id":"1812","type":"CategoricalTicker"},{"attributes":{},"id":"1823","type":"HelpTool"},{"attributes":{},"id":"1819","type":"WheelZoomTool"},{"attributes":{},"id":"1818","type":"PanTool"},{"attributes":{},"id":"1809","type":"LinearScale"},{"attributes":{"bottom_units":"screen","coordinates":null,"fill_alpha":0.5,"fill_color":"lightgrey","group":null,"left_units":"screen","level":"overlay","line_alpha":1.0,"line_color":"black","line_dash":[4,4],"line_width":2,"right_units":"screen","syncable":false,"top_units":"screen"},"id":"1824","type":"BoxAnnotation"},{"attributes":{"source":{"id":"1832"}},"id":"1837","type":"CDSView"},{"attributes":{"coordinates":null,"data_source":{"id":"1832"},"glyph":{"id":"1833"},"group":null,"hover_glyph":null,"muted_glyph":{"id":"1835"},"nonselection_glyph":{"id":"1834"},"view":{"id":"1837"}},"id":"1836","type":"GlyphRenderer"},{"attributes":{"fill_alpha":{"value":0.2},"fill_color":{"value":"#1f77b4"},"hatch_alpha":{"value":0.2},"line_alpha":{"value":0.2},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"width":{"value":0.5},"x":{"field":"x"}},"id":"1835","type":"VBar"},{"attributes":{},"id":"1847","type":"Selection"},{"attributes":{"coordinates":null,"group":null},"id":"1838","type":"Title"},{"attributes":{"tools":[{"id":"1818"},{"id":"1819"},{"id":"1820"},{"id":"1821"},{"id":"1822"},{"id":"1823"}]},"id":"1825","type":"Toolbar"},{"attributes":{"overlay":{"id":"1824"}},"id":"1820","type":"BoxZoomTool"},{"attributes":{},"id":"1846","type":"UnionRenderers"},{"attributes":{"factors":["a","b","c","d","e"]},"id":"1803","type":"FactorRange"},{"attributes":{},"id":"1821","type":"SaveTool"},{"attributes":{},"id":"1815","type":"BasicTicker"},{"attributes":{},"id":"1845","type":"AllLabels"},{"attributes":{"below":[{"id":"1811"}],"center":[{"id":"1813"},{"id":"1817"}],"left":[{"id":"1814"}],"renderers":[{"id":"1836"}],"title":{"id":"1838"},"toolbar":{"id":"1825"},"x_range":{"id":"1803"},"x_scale":{"id":"1807"},"y_range":{"id":"1805"},"y_scale":{"id":"1809"}},"id":"1802","subtype":"Figure","type":"Plot"},{"attributes":{"coordinates":null,"formatter":{"id":"1844"},"group":null,"major_label_policy":{"id":"1845"},"ticker":{"id":"1812"}},"id":"1811","type":"CategoricalAxis"},{"attributes":{},"id":"1842","type":"AllLabels"},{"attributes":{},"id":"1844","type":"CategoricalTickFormatter"},{"attributes":{"data":{"top":[4,5,6],"x":["a","d","e"]},"selected":{"id":"1847"},"selection_policy":{"id":"1846"}},"id":"1832","type":"ColumnDataSource"},{"attributes":{"axis":{"id":"1811"},"coordinates":null,"group":null,"ticker":null},"id":"1813","type":"Grid"},{"attributes":{},"id":"1805","type":"DataRange1d"},{"attributes":{"fill_color":{"value":"#1f77b4"},"line_color":{"value":"#1f77b4"},"top":{"field":"top"},"width":{"value":0.5},"x":{"field":"x"}},"id":"1833","type":"VBar"},{"attributes":{},"id":"1822","type":"ResetTool"},{"attributes":{},"id":"1807","type":"CategoricalScale"},{"attributes":{},"id":"1841","type":"BasicTickFormatter"}],"root_ids":["1802"]},"title":"Bokeh Application","version":"2.4.2"}}
</script>
<script type="text/javascript">
(function() {
const fn = function() {
Bokeh.safely(function() {
(function(root) {
function embed_document(root) {
const docs_json = document.getElementById('1981').textContent;
const render_items = [{"docid":"883b6c59-c219-42d0-825d-9acf30299e7b","root_ids":["1802"],"roots":{"1802":"1cc70986-5765-4f3c-8dab-ebcc901298e2"}}];
root.Bokeh.embed.embed_items(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
});
};
if (document.readyState != "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
})();
</script>
<p>There are also extra commands and arguments you can pass to bokeh to display an title for the plot, for each of the axis, for the color of the bars, and so on.</p>
<p>If you want to dive deep into that documentation, check out these resources:</p>
<ul>
<li><a href="http://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html#bars">Bar plots / histograms</a></li>
<li><a href="http://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html#categorical-axes">Categorical axes</a></li>
<li><a href="http://bokeh.pydata.org/en/latest/docs/user_guide/styling.html">Everything to do with styling plots</a></li>
<li><a href="http://bokeh.pydata.org/en/latest/docs/user_guide/plotting.html">Basic plotting for other types of graphs</a></li>
</ul>
<p>If you want to add more flair to your histogram from this exercise, there are many resources on the web to help you out!</p>
<p>Happy coding!</p>
https://practicepython.org/blog/2017/03/24/install-pythonInstalling Python to Get Started2017-03-24T00:00:00+00:002017-03-24T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>Written by Michele Pratusevich.</em> One barrier to learning programming is getting your development environment set up. Whether you are on Windows, OSX, or Ubuntu, this guide will help you set up your computer with a basic Python installation so you can start your own journey with Python!</p>
<!--more-->
<p>“I haven’t installed Python.” “I don’t want to mess up my computer by installing new software.” “I have a Windows machine.” I’ve heard all of these and more from readers as an excuse for not starting to learn Python. Never fear! Installing Python is a painless process for all 3 major operating systems (disclaimer: I haven’t tried installing it on anything except Windows, OSX, and Ubuntu so I can’t speak for any other system), and there are even installation-free alternatives if you just want to play around with basic syntax and code.</p>
<p>I’ll go through my recommendations for installing Python on Windows, OSX, and Ubuntu, and then list a few no-installation-required options. You are not limited by your operating system!</p>
<h1 id="the-ultimate-python-installation-recommendation">The ultimate Python installation recommendation</h1>
<p>Whether you are on Windows, OSX, or Ubuntu, and want to quickly get started with Python, my recommendation is to install <a href="https://www.continuum.io/downloads">Anaconda Python</a>. The company that distributes Anaconda specifically packages Python and a few useful libraries, such as <a href="http://www.numpy.org/">Numpy</a> and <a href="http://scipy.org">Scipy</a> into an easy installer. It will create a desktop icon for Python, and will install a tool called <code class="language-plaintext highlighter-rouge">conda</code> that you can then use to install any extra Python packages you need.</p>
<p>Another benefit: you don’t need administrative permissions! You can install Anaconda anywhere you have write permissions, such as your user’s home directory.</p>
<p>You can read the official Anaconda installation recommendations <a href="https://conda.io/docs/install/full.html">on their docs page</a>. It’s as easy as downloading and running the installer!</p>
<h1 id="windows">Windows</h1>
<p>You can’t write your program in Microsoft Word. What you need is a text editor - a program that lets you edit text (programs!) without getting in your way. On Windows, you can use regular old Notepad, or a souped-up free version called <a href="https://notepad-plus-plus.org/">Notepad++</a>. You can also install my favorite text editor, <a href="https://www.sublimetext.com/3">Sublime Text</a>, on Windows. Regardless of which editor you use, you can run your</p>
<p>If you can’t install packages on your Windows computer because it is a shared computer, check out the section on <a href="#no-installation-required">options where you don’t need to install anything</a>.</p>
<h1 id="osx">OSX</h1>
<p>For text editors, OSX comes with Xcode, but I recommend using a text editor like <a href="https://www.sublimetext.com/3">Sublime Text</a>, which you can download for free.</p>
<p>For those who will be doing more serious Python development or want to use the command-line to install Python, I recommend doing the following (not for the faint of heart):</p>
<ol>
<li>Install <a href="https://brew.sh/">Homebrew</a> using the instructions on their website. Homebrew calls itself “the missing package manager for OSX” - it is definitively the easiest way to install and maintain software for development on OSX.</li>
<li>Do <code class="language-plaintext highlighter-rouge">brew install python3</code>. (You’re using Python 3, right?)</li>
</ol>
<p>Now you can run Python from the command line by running <code class="language-plaintext highlighter-rouge">python3</code> to get a Python shell, or writing a Python program in a text editor and running <code class="language-plaintext highlighter-rouge">python3 MyProgram.py</code>. To install Python packages, you run <code class="language-plaintext highlighter-rouge">pip3 install PACKAGE_NAME</code> on the command line.</p>
<h1 id="ubuntu">Ubuntu</h1>
<p>Yep, you can install Anaconda Python for Ubuntu as well. It’s a great option, even for experienced terminal users.</p>
<p>But if you don’t want to use Anaconda, you can use <code class="language-plaintext highlighter-rouge">apt</code> to install Python 3:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>apt-get <span class="nb">install </span>python3</code></pre></figure>
<p>Then, to write Python programs, use your favorite text editor (have you guessed that my favorite is <a href="https://www.sublimetext.com/3">Sublime Text</a>?), and run your Python programs by doing</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">python3 MY_PYTHON_FILE.py</code></pre></figure>
<p><code class="language-plaintext highlighter-rouge">apt</code> also installs <code class="language-plaintext highlighter-rouge">pip3</code>, which is the Python-recommended way of installing Python packages. So if you want to install <code class="language-plaintext highlighter-rouge">numpy</code>, you would do</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">pip3 <span class="nb">install </span>numpy</code></pre></figure>
<p>And it will install <code class="language-plaintext highlighter-rouge">numpy</code> to let you write <code class="language-plaintext highlighter-rouge">import numpy</code> at the top of your Python programs.</p>
<h1 id="no-installation-required">No installation required</h1>
<p>If you can’t (or don’t want to) install Python on your computer, there are a number of options for learning to code in Python that don’t require installing any software. You can even do some of these options from an iPad or Android/Windows tablet!</p>
<p>My list is not comprehensive, and if you find another solution out there that works for you, please <a href="mailto:mail@practicepython.org">email me and let me know</a>.</p>
<ul>
<li><a href="http://pythontutor.com/live.html#mode=edit">Python Tutor</a> - Created by a friend and former colleague at MIT, Python Tutor lets you write Python in the cloud, and will even visualize the internals of the code for you. If you are the kind of person that learns visually or wants to see exactly what is happening in the background, I could not recommend Python Tutor more. Be warned, the functionality is very limited, but using Python Tutor should get you through the first 10 or so exercises on Practice Python.</li>
<li><a href="https://repl.it/languages/python3">repl.it</a> - A cloud-based Python3 editor that lets you write and run code directly in your browser. You can even sign up for an account with Gmail, Github, or Facebook, to save and go back to your work. This platform is great for getting started, but it might not have all the packages installed that you want to use.</li>
<li><a href="http://pythonfiddle.com/">Python Fiddle</a> - Based off of JSFiddle, PythonFiddle lets you write and run small programs in your web browser. Same deal as with repl.it - they might not have all the packages you need, but it will definitely get you started.</li>
<li><a href="https://c9.io/">Cloud 9</a> - If you are more of a developer-type and want a more hardcore online development environment, Cloud 9 lets you basically set up a virtual machine in the cloud. You can use it to install any custom packages and run any custom code you want. I wouldn’t recommend this as a place to start, but if you want a Linux (Ubuntu) environment you have lots of control over and want to be able to install any packages you want, it is worth looking into.</li>
</ul>
<p>While using browser-based editors is fantastic for learners and casual coders, if you are going to be doing any serious data processing or multi-file coding, I suggest you install Python on a computer so you can have more control and processing power on your local machine.</p>
<h1 id="final-thoughts">Final thoughts</h1>
<p>Your environment doesn’t matter - if you want to learn how to program, solve logic problems, and think analytically, there are many options out there for you! Just pick one and get started.</p>
<p><a href="/exercise/2014/01/29/01-character-input.html">Here is a link to the first exercise on Practice Python. Start coding!</a></p>
https://practicepython.org/solution/2017/03/19/35-birthday-months-solutions35 Birthday Months Solutions2017-03-19T00:00:00+00:002017-03-19T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In the <a href="/exercise/2017/02/06/34-birthday-json.html">previous exercise</a> we saved information about famous scientists’ names and birthdays to disk. In this exercise, load that JSON file from disk, extract the months of all the birthdays, and count how many scientists have a birthday in each month.</p>
<p>Your program should output something like:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="p">{</span>
<span class="s">"May"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="s">"November"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="s">"December"</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">}</span></code></pre></figure>
<h2 id="reader-solution">Reader solution</h2>
<p>Here is one reader solution using built-in Counters. This reader’s solution did not specify what kind of format the months have to be in, but as you can see from their use of <code class="language-plaintext highlighter-rouge">x.split()[0]</code> to extract the months that they expect the month format to be of the type “May 5, 2010”.</p>
<script src="https://gist.github.com/esclavosoy/19829e8486f88da3ab42b1fedc3f6936.js"></script>
<h2 id="my-solution">My solution</h2>
<p>In the <a href="/exercise/2017/02/06/34-birthday-json.html">previous exercise</a>, I saved birthday information in a slightly different format, so I had to use a slightly different method to extract the months. In my dictionary, the birthdays were saved in the format “MM/DD/YYYY”, or the standard date format we use in the US. My <code class="language-plaintext highlighter-rouge">birthdays.json</code> file looked like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="p">{</span>
<span class="s">"Albert Einstein"</span><span class="p">:</span> <span class="s">"03/14/1879"</span><span class="p">,</span>
<span class="s">"Ada Byron Lovelace"</span><span class="p">:</span> <span class="s">"12/10/1815"</span><span class="p">,</span>
<span class="s">"Benjamin Franklin"</span><span class="p">:</span> <span class="s">"01/17/1706"</span>
<span class="p">}</span></code></pre></figure>
<p>To count how many birthdays are in each month, what we need to do is:</p>
<ol>
<li>Extract the number that represents the month</li>
<li>Convert that number to a string</li>
<li>Print the result</li>
</ol>
<p>Here is my code to do that:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">json</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"birthdays.json"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">birthdays</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="n">num_to_string</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">1</span><span class="p">:</span> <span class="s">"January"</span><span class="p">,</span>
<span class="mi">2</span><span class="p">:</span> <span class="s">"February"</span><span class="p">,</span>
<span class="mi">3</span><span class="p">:</span> <span class="s">"March"</span><span class="p">,</span>
<span class="mi">4</span><span class="p">:</span> <span class="s">"April"</span><span class="p">,</span>
<span class="mi">5</span><span class="p">:</span> <span class="s">"May"</span><span class="p">,</span>
<span class="mi">6</span><span class="p">:</span> <span class="s">"June"</span><span class="p">,</span>
<span class="mi">7</span><span class="p">:</span> <span class="s">"July"</span><span class="p">,</span>
<span class="mi">8</span><span class="p">:</span> <span class="s">"August"</span><span class="p">,</span>
<span class="mi">9</span><span class="p">:</span> <span class="s">"September"</span><span class="p">,</span>
<span class="mi">10</span><span class="p">:</span> <span class="s">"October"</span><span class="p">,</span>
<span class="mi">11</span><span class="p">:</span> <span class="s">"November"</span><span class="p">,</span>
<span class="mi">12</span><span class="p">:</span> <span class="s">"December"</span>
<span class="p">}</span>
<span class="n">months</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">birthday_string</span> <span class="ow">in</span> <span class="n">birthdays</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="n">month</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">birthday_string</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"/"</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">months</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">num_to_string</span><span class="p">[</span><span class="n">month</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="n">Counter</span><span class="p">(</span><span class="n">months</span><span class="p">))</span></code></pre></figure>
<p>And the output you will see is:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">Counter</span><span class="p">({</span><span class="s">'January'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s">'March'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s">'December'</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span></code></pre></figure>
<p>Happy coding!</p>
https://practicepython.org/blog/2017/03/11/talk-python-to-meGuido van Rossum on Talk Python to Me2017-03-11T00:00:00+00:002017-03-11T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>This post is written by Michele Pratusevich.</em>
I occasionally listen to a podcast called <em>Talk Python to Me</em> on my commute. Last week I listened to the <a href="https://talkpython.fm/episodes/show/100/python-past-present-and-future-with-guido-van-rossum">100th episode</a>, where Guido van Rossum, the creator of the Python language, talks about how he got into programming and his ideas about the future of Python.</p>
<!--more-->
<p>For the <a href="https://talkpython.fm/episodes/show/100/python-past-present-and-future-with-guido-van-rossum">100th episode</a> of the <a href="https://talkpython.fm"><em>Talk Python to Me</em> postcast</a>, host Michael Kennedy talked to Guido van Rossum, the creator of Python. Guido is known in the Python community as the “benevolent dictator for life” (BDFL). This means his job in the Python community is much like a CEO - have a vision for the language, develop new ideas, and evangelize. He was the original creator of Python, but now there are a group of core developers of whom Guido is just one. However, his perspective and ideas are a guiding force in the Python community. One thing I love about Guido’s ideas is his firmness in making Python open source. Because Python is an open-source language, anyone can look at the <a href="https://github.com/python/cpython">Github repository</a> and look at the source code of Python!</p>
<p><img class="post-img post-img-max" src="https://upload.wikimedia.org/wikipedia/commons/6/66/Guido_van_Rossum_OSCON_2006.jpg" /></p>
<p>On the podcast, Michael, the host, asked Guido how he got into programming. Guido started as an electronics tinkerer and moved to punch-card programming, all the way to designing programming languages. I really enjoyed Guido’s descriptions of what programming was like in the old days. In fact, before he started working on Python, he worked on a language called <a href="https://en.wikipedia.org/wiki/ABC_programming_language">ABC</a>. As he says many times on the podcast, Guido did not design ABC, but he worked on the implementation. It did influence some of the early design decisions in the Python language. I especially enjoyed the description of distributing a new language to academic groups that wanted to use ABC - he carried it on storage devices in his luggage! This was before the internet, so this was the only way to distribute software! My, how times have changed, and how lucky we are…</p>
<p>The discussion then shifted to how Python evolves. Turns out, Guido doesn’t have grand visions for the language, and the language evolves based on the needs of the community. There was a discussion of how things got added to the standard library (i.e. all the packages you can do <code class="language-plaintext highlighter-rouge">import FOO</code> without needing to install a new package), and what makes a good core standard library package. The core developers of Python make this possible, and of course the conversation shifted to diversity and inclusion. The number of female or people of color developers is very small, and Guido is making efforts to improve the situation. His attitude is positive towards inclusion, and he believes in diversity to make progress. As you can see from the Python Diversity home page, the Python Software Foundation (PSF) has a diversity mission:</p>
<p><img class="post-img post-img-max" src="/assets/imgs/python-diversity.png" /></p>
<p>One of the goals of the Practice Python blog is to make Python accessible to everyone, and I get some of my inspiration from Guido van Rossum.</p>
<p>You can read more about Guido on his <a href="https://en.wikipedia.org/wiki/Guido_van_Rossum">wikipedia page</a>, or better yet, from his <a href="https://gvanrossum.github.io/">personal home page</a>. I recommend listening to the podcast yourself. <a href="https://talkpython.fm/episodes/show/100/python-past-present-and-future-with-guido-van-rossum">It was a great listen!</a>. Thanks Michael and <em>Talk Python to Me</em>.</p>
<p>Happy Coding!</p>
https://practicepython.org/exercise/2017/02/28/35-birthday-months35 Birthday Months2017-02-28T00:00:00+00:002017-02-28T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In the <a href="/exercise/2017/02/06/34-birthday-json.html">previous exercise</a> we saved information about famous scientists’ names and birthdays to disk. In this exercise, load that JSON file from disk, extract the months of all the birthdays, and count how many scientists have a birthday in each month.</p>
<p>Your program should output something like:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="p">{</span>
<span class="s">"May"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="s">"November"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="s">"December"</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">}</span></code></pre></figure>
<h2 id="discussion">Discussion</h2>
<p>You already have the skills to achieve this exercise with concepts we’ve already covered: <a href="/exercise/2014/02/15/03-list-less-than-ten.html">for loops</a>, <a href="/exercise/2014/12/06/22-read-from-file.html">dictionaries</a>, and basic arithmetic. However, I want to talk about a Python built-in called a <code class="language-plaintext highlighter-rouge">Counter</code>.</p>
<p>A <a href="https://docs.python.org/3/library/collections.html#collections.Counter"><code class="language-plaintext highlighter-rouge">Counter</code></a> takes a list and counts how many of each element were in the list. To use the Counter, first import it from <code class="language-plaintext highlighter-rouge">collections</code>:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span></code></pre></figure>
<p>This lets you use the <code class="language-plaintext highlighter-rouge">Counter</code> data structure built into Python in your program. Then, give it a list:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">sandwiches</span> <span class="o">=</span> <span class="p">[</span><span class="s">"ham"</span><span class="p">,</span> <span class="s">"cheese"</span><span class="p">,</span> <span class="s">"roast beef"</span><span class="p">,</span> <span class="s">"ham"</span><span class="p">,</span> <span class="s">"cheese"</span><span class="p">,</span> <span class="s">"roast beef"</span><span class="p">,</span> <span class="s">"ham"</span><span class="p">]</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="n">sandwiches</span><span class="p">)</span></code></pre></figure>
<p>If you <code class="language-plaintext highlighter-rouge">print(c)</code>, you will see this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">Counter</span><span class="p">({</span><span class="s">"ham"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s">"roast beef"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s">"cheese"</span><span class="p">:</span> <span class="mi">2</span><span class="p">})</span></code></pre></figure>
<p>This means there are 3 <code class="language-plaintext highlighter-rouge">ham</code>, 2 <code class="language-plaintext highlighter-rouge">roast beef</code>, and 2 <code class="language-plaintext highlighter-rouge">cheese</code> sandwiches in my list. I can get this information directly from the <code class="language-plaintext highlighter-rouge">Counter</code>:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="s">"There are {} ham sandwiches"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="s">"ham"</span><span class="p">]))</span>
<span class="n">There</span> <span class="n">are</span> <span class="mi">3</span> <span class="n">ham</span> <span class="n">sandwiches</span></code></pre></figure>
<p>Hope this is useful!</p>
https://practicepython.org/solution/2017/02/25/34-birthday-json-solutions34 Birthday Json Solutions2017-02-25T00:00:00+00:002017-02-25T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In the <a href="/exercise/2017/01/24/33-birthday-dictionaries.html">previous exercise</a> we created a dictionary of famous scientists’ birthdays. In this exercise, modify your program from <a href="/exercise/2017/01/24/33-birthday-dictionaries.html">Part 1</a> to load the birthday dictionary from a JSON file on disk, rather than having the dictionary defined in the program.</p>
<p><strong>Bonus</strong>: Ask the user for another scientist’s name and birthday to add to the dictionary, and update the JSON file you have on disk with the scientist’s name. If you run the program multiple times and keep adding new names, your JSON file should keep getting bigger and bigger.</p>
<h2 id="sample-solution">Sample solution</h2>
<p>Here is one reader’s solution to the exercise:</p>
<script src="https://gist.github.com/Evilizard83/bcfa5b0e4579737a7f4ad28676347832.js"></script>
<p>Happy coding!</p>
https://practicepython.org/blog/2017/02/09/python2-and-3Python 2 or 3? Beginners shouldn't care!2017-02-09T00:00:00+00:002017-02-09T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>When you are starting to learn Python, you have to decide whether to learn Python 2 or Python 3. Good news is, when you’re starting out, it doesn’t matter! In beginner code, the differences are minimal - in this post we will discuss the 3 differences beginners will notice: print, input, and division. Why is it different and why is it a problem? The <em>interpreters</em> are different!</p>
<!--more-->
<h1 id="python-2-vs-python-3">Python 2 vs Python 3</h1>
<p>The debate continues and will continue into the forseeable future: do I learn Python 2 or Python 3? I believe you should learn Python 3 (and if you want to read a more detailed discussion of why, I wrote about it <a href="/why-practice-python">in my introductory post</a>). Instead, I want to talk about how you can add a few lines to simple Python 3 code (which this site uses in the examples) that will let you run the code through Python 2.</p>
<h1 id="interpreters">Interpreters</h1>
<p>First, a quick word on <em>interpreters</em>. What is an interpreter? In English the word <em>interpreter</em> means someone or something that can extract meaning out from words or text. In Python it is the same thing - the Python <em>interpreter</em> translates your Python code that looks something like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">month</span> <span class="o">=</span> <span class="s">"December"</span>
<span class="n">day</span> <span class="o">=</span> <span class="s">"06"</span>
<span class="n">year</span> <span class="o">=</span> <span class="s">"2016"</span>
<span class="k">print</span><span class="p">(</span><span class="s">"The date is: {} {}, {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">month</span><span class="p">,</span> <span class="n">day</span><span class="p">,</span> <span class="n">year</span><span class="p">))</span></code></pre></figure>
<p>Into code that a computer can interpret <sup>1</sup>, like this:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">01000100100001
00001010010111
10111101010101
01001010101001</code></pre></figure>
<p><sup>1</sup> <em>I have no idea if the code compiles to this lovely sequence of 0s and 1s. It is just an illustration.</em></p>
<p>When you run a Python program through the Python shell, through hitting “play” in IDLE, or by running <code class="language-plaintext highlighter-rouge">python3</code> in the command line, what you are doing is telling the interpreter to start translating.</p>
<p>How does this relate to Python 2 and Python 3? Well, Python 2 and Python 3 are the same language, but they rely on slightly different interpreters to translate. For example, a <em>syntax difference</em> between Python 2 and 3 is how you print something to the screen. In Python 2 you do <code class="language-plaintext highlighter-rouge">print "Michele"</code> but in Python 3 you do <code class="language-plaintext highlighter-rouge">print("Michele")</code>. The meaning is the same but the way you write it is different. The syntax for Python 2 is not understood by the Python 3 interpreter, and vice versa. The other kind of difference is an <em>interpretation difference</em> - the syntax is the same, but the meaning is different. An example is division, which we will discuss below. Both kinds of differences cause errors in your program, and you must be aware of it.</p>
<p>Let’s talk about the 3 small differences you as a beginner will notice.</p>
<h1 id="syntax-differences-between-python-2-and-python-3">Syntax differences between Python 2 and Python 3</h1>
<p>For beginners, there are a few important differences (both in syntax and interpretation) between Python 2 and Python 3. We will discuss 3 of them here:</p>
<ol>
<li>printing to the screen (<em>syntax</em>)</li>
<li>user input (<em>syntax</em>)</li>
<li>division (<em>interpretation</em>)</li>
</ol>
<p>There are many many manyy more small differences that I won’t get into, mostly because they won’t affect you being able to get your hands dirty with Python! If you want to read more about the changes to the Python language introduced in the various versions of Python 3, I have included links to each of the changelogs from Python 3.0 to Python 3.6 <a href="#readmore">here</a>.</p>
<h2 id="printing">Printing</h2>
<p>The first difference most people will notice between Python 2 and Python 3 is printing information to the screen. The difference is straightforward:</p>
<table style="border-spacing: 10px; padding: 10px; margin: 0 auto;">
<thead>
<tr style="border-bottom: 1px solid black;">
<th style="border-right: 1px solid black;">Python 2</th>
<th>Python 3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border-right: 1px solid black;">
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span> <span class="s">"my string"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span><span class="p">(</span><span class="s">"my string"</span><span class="p">)</span></code></pre></figure>
</td>
</tr>
</tbody>
</table>
<p>In Python 2, <code class="language-plaintext highlighter-rouge">print</code> is an <em>operator</em>, which means it operates on whatever comes after it. In Python 3, <code class="language-plaintext highlighter-rouge">print</code> is a function that takes an argument.</p>
<p>So if you get an error like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span> <span class="s">"Michele"</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span>
<span class="k">print</span> <span class="s">"Michele"</span>
<span class="o">^</span>
<span class="nb">SyntaxError</span><span class="p">:</span> <span class="n">Missing</span> <span class="n">parentheses</span> <span class="ow">in</span> <span class="n">call</span> <span class="n">to</span> <span class="s">'print'</span></code></pre></figure>
<p>It means you were trying to use Python 2 <code class="language-plaintext highlighter-rouge">print</code> syntax in Python 3. Just add parentheses and you’re good to go. Fortunately, this capability has been back-ported to Python 2, so you can run Python 3 print statements through Python 2 and you should be all set. In case you want to be extra sure, if you are running code through a Python 2 interpreter, just add the following import to the header:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">printfunction</span></code></pre></figure>
<p>It will make sure you can run <code class="language-plaintext highlighter-rouge">print</code> as a function in Python 2.</p>
<h2 id="user-input">User input</h2>
<p>The next difference a beginner will notice is the function that is used to take in user input. In Python 2, the <code class="language-plaintext highlighter-rouge">raw_input()</code> function was used. However, this function is removed in Python 3 and is replaced with the <code class="language-plaintext highlighter-rouge">input()</code> function instead. Beware - the <code class="language-plaintext highlighter-rouge">input()</code> function existed in Python 2 as well, but it was a LOT less useful, and had wrong unexpected behavior.</p>
<p>If you try to use <code class="language-plaintext highlighter-rouge">raw_input()</code> in your Python 3 programs, you will get an error like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">"input something: "</span><span class="p">)</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s">'raw_input'</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span></code></pre></figure>
<p>So use <code class="language-plaintext highlighter-rouge">input()</code> instead.</p>
<h2 id="division">Division</h2>
<p>The default division behavior is different between Python 2 and 3.</p>
<table style="border-spacing: 10px; padding: 10px; margin: 0 auto;">
<thead>
<tr style="border-bottom: 1px solid black;">
<th style="border-right: 1px solid black; padding: 15px;">Python 2</th>
<th>Python 3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border-right: 1px solid black;">
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span>
<span class="mi">0</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span>
<span class="mf">0.666666</span></code></pre></figure>
</td>
</tr>
</tbody>
</table>
<p>In Python 2, the division is integer division - two integers that are divided must return an integer, and the convention is that this is done with the <code class="language-plaintext highlighter-rouge">floor()</code> function, or that the integer returned from the division is just the integer part, not rounded. In Python 3, two integers divided can return a decimal. Strangely, if you do <code class="language-plaintext highlighter-rouge">2.0 / 3</code> in Python 2, the result will be <code class="language-plaintext highlighter-rouge">0.6666666</code> as you expect. But remembering to add the <code class="language-plaintext highlighter-rouge">.0</code> at the end is hard, and can lead to errors in your programs.</p>
<p>Instead, to make Python 2 division behave just like Python 3 division, just add the following import to your program to take advantage of the fact that Python’s future (i.e. Python 3) has fixed this annoyance:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">division</span></code></pre></figure>
<p>Yes, we are learning division from the future.</p>
<h1 id="summary">Summary</h1>
<p>For beginners, we talked about 3 small syntax and interpretation differences between Python 2 and Python 3. The differences are so small, that you shouldn’t debate about which to learn! Here are the differences summarized in a single table:</p>
<table style="border-spacing: 10px; padding: 5px; margin: 0 auto;">
<thead>
<tr style="border-bottom: 1px solid black;">
<th></th>
<th style="border-right: 1px solid black;">Python 2</th>
<th>Python 3</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 1px solid black;">
<td style="border-right: 1px solid black;">
Printing
</td>
<td style="border-right: 1px solid black;">
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span> <span class="s">"my string"</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span><span class="p">(</span><span class="s">"my string"</span><span class="p">)</span></code></pre></figure>
</td>
</tr>
<tr style="border-bottom: 1px solid black;">
<td style="border-right: 1px solid black;">
User input
</td>
<td style="border-right: 1px solid black;">
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="nb">raw_input</span><span class="p">()</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="nb">input</span><span class="p">()</span></code></pre></figure>
</td>
</tr>
<tr style="border-bottom: 1px solid black;">
<td style="border-right: 1px solid black;">
Division
</td>
<td style="border-right: 1px solid black;">
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span>
<span class="mi">0</span></code></pre></figure>
</td>
<td>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="mi">2</span> <span class="o">/</span> <span class="mi">3</span>
<span class="mf">0.666666</span></code></pre></figure>
</td>
</tr>
</tbody>
</table>
<p>And, in case you have Python 2 but want to run the code examples from this blog (which are in Python 3), all you need to do is add a few imports to the top of your Python 2 code for your Python 2 interpreter:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">division</span><span class="p">,</span> <span class="n">printfunction</span></code></pre></figure>
<h1 id="read-more"><a name="readmore">Read more</a></h1>
<p>We haven’t even begun to scratch the surface of the new features that the various releases of Python 3 have added to the language - we focused on 3 small things that beginners will notice.</p>
<p>If you want to read about ALL the new features of Python 3 (not just the 3 tip-of-the-iceberg features), you can read the various “whats new” pages for the latest few releases of Python:</p>
<ul>
<li><a href="https://docs.python.org/3/whatsnew/3.0.html">What’s new in Python 3.0</a></li>
<li><a href="https://docs.python.org/3.3/whatsnew/3.3.html">What’s new in Python 3.3</a></li>
<li><a href="https://docs.python.org/3.4/whatsnew/3.4.html">What’s new in Python 3.4</a></li>
<li><a href="https://docs.python.org/3.5/whatsnew/3.5.html">What’s new in Python 3.5</a></li>
<li><a href="https://docs.python.org/3.6/whatsnew/3.6.html">What’s new in Python 3.6</a></li>
</ul>
<p>Happy Coding!</p>
https://practicepython.org/exercise/2017/02/06/34-birthday-json34 Birthday Json2017-02-06T00:00:00+00:002017-02-06T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In the <a href="/exercise/2017/01/24/33-birthday-dictionaries.html">previous exercise</a> we created a dictionary of famous scientists’ birthdays. In this exercise, modify your program from <a href="/exercise/2017/01/24/33-birthday-dictionaries.html">Part 1</a> to load the birthday dictionary from a JSON file on disk, rather than having the dictionary defined in the program.</p>
<p><strong>Bonus</strong>: Ask the user for another scientist’s name and birthday to add to the dictionary, and update the JSON file you have on disk with the scientist’s name. If you run the program multiple times and keep adding new names, your JSON file should keep getting bigger and bigger.</p>
<h2 id="discussion">Discussion</h2>
<p>In a previous exercise we talked about <a href="/exercise/2014/11/30/21-write-to-a-file.html">how to save information to a .txt file on disk</a>, but in this exercise we are talking about writing a different kind of file format called JSON.</p>
<p>The JSON file format was developed in the early 2000s as a standard for how web servers would pass data back and forth. It is still used for web server communication today, and it conveniently is also a way we can store dictionary-like data in a file on disk. The JSON format specifies a way to <em>serialize</em> (turn into a string) a dictionary or list, which then means that string can be written to disk or passed to another application. JSON is meant to store dictionary-like data both in a readable way for humans, and in a compact way that can be read by computers. Because it is a standard format, you can write JSON in one language and read JSON from another language to effectively pass information between the two programs or applications. You can read more about the history of JSON on <a href="https://en.wikipedia.org/wiki/JSON">the wikipedia article</a>.</p>
<p>Here is an example of JSON:</p>
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Michele"</span><span class="p">,</span><span class="w">
</span><span class="nl">"shirt_color"</span><span class="p">:</span><span class="w"> </span><span class="s2">"blue"</span><span class="p">,</span><span class="w">
</span><span class="nl">"laptops"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"brand"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Lenovo"</span><span class="p">,</span><span class="w">
</span><span class="nl">"operating_system"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Ubuntu"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"brand"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Apple"</span><span class="p">,</span><span class="w">
</span><span class="nl">"operating_system"</span><span class="p">:</span><span class="w"> </span><span class="s2">"OSX"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"has_a_dog"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"items_on_desk"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"mug"</span><span class="p">,</span><span class="w"> </span><span class="s2">"pen"</span><span class="p">,</span><span class="w"> </span><span class="s2">"monitor"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span></code></pre></figure>
<p>Notice how you can mix dictionaries and lists. In this example the top-level container is a dictionary, with the keys <code class="language-plaintext highlighter-rouge">name</code>, <code class="language-plaintext highlighter-rouge">shirt_color</code>, <code class="language-plaintext highlighter-rouge">laptops</code>, <code class="language-plaintext highlighter-rouge">has_a_dog</code>, and <code class="language-plaintext highlighter-rouge">items_on_desk</code>. The keys can be lists, strings, booleans, or other dictionaries. Usually you don’t write JSON by hand (but it is very readable so you easily could). One of my favorite tools to test whether you’ve written valid JSON is this free <a href="http://jsonlint.com/">JSON validator</a> - just paste your JSON in there and it tells you if it will be read by a program that understands JSON.</p>
<p>There is a built-in Python library for reading and writing JSON files, so you don’t have to worry about how your dictionaries and lists are going to be turned into the right format!</p>
<p>As long as the data you want to store is either a dictionary or a list of dictionaries, writing JSON is straightforward. First, import the <a href="https://docs.python.org/3/library/json.html"><code class="language-plaintext highlighter-rouge">json</code> library</a> (no installation needed, it is built in to Python) and initialize some dictionary:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">json</span>
<span class="n">info_about_me</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"name"</span><span class="p">:</span> <span class="s">"Michele"</span><span class="p">,</span>
<span class="s">"has_a_dog"</span><span class="p">:</span> <span class="bp">False</span>
<span class="p">}</span></code></pre></figure>
<p>Then, to save your dictionary to disk you need to open a file and use the <code class="language-plaintext highlighter-rouge">json.dump()</code> method. Remember to use the <code class="language-plaintext highlighter-rouge">w</code> flag when opening a file for writing:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"info.json"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">json</span><span class="p">.</span><span class="n">dump</span><span class="p">(</span><span class="n">info_about_me</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span></code></pre></figure>
<p>And you will have saved a file called <code class="language-plaintext highlighter-rouge">info.json</code> in the same directory as your Python program. The dictionary <code class="language-plaintext highlighter-rouge">info_about_me</code> will be saved to disk, but the variable name will not be. Basically, JSON won’t remember the name of the variable you saved your dictionary in. If you open the file with a text editor (Notepad++, vim, emacs, Sublime Text, etc.), you will just see:</p>
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Michele"</span><span class="p">,</span><span class="w">
</span><span class="nl">"has_a_dog"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span><span class="p">}</span></code></pre></figure>
<p>Alternatively, you can also manually create a JSON file and type JSON directly into it (passing it through <a href="http://jsonlint.com/">the JSON validator</a> of course!). Just save the file with the <code class="language-plaintext highlighter-rouge">.json</code> extension and copy the dictionary directly into the file.</p>
<p>Now I can use the information about me that I saved to disk in another program (written in a completely different file) to do something like printing a message. When I saved the JSON file, the variable name of my dictionary was not saved with it, so when I load the JSON file I need to save it into a variable. I can use the same <code class="language-plaintext highlighter-rouge">json</code> library to do this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">json</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"info.json"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">info</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">if</span> <span class="n">info</span><span class="p">[</span><span class="s">"has_a_dog"</span><span class="p">]:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"{} has a dog"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">info</span><span class="p">[</span><span class="s">"name"</span><span class="p">]))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"{} does not have a dog"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">info</span><span class="p">[</span><span class="s">"name"</span><span class="p">]))</span></code></pre></figure>
<p>When this program runs, the output should be:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">Michele does not have a dog</code></pre></figure>
<p>Notice how when I loaded the JSON file I used a different name than when I saved it - this is because the variable names don’t get saved together with the JSON data, so you do not have to use the same variable names to save and load JSON.</p>
<p>Now that you know about JSON, you can use it to do a number of things:</p>
<ul>
<li>Save data to disk that can be shared by people and programs.</li>
<li>Constantly update data that needs to be shared by re-saving and re-load to disk.</li>
<li>Save data from a program that a human can read and manually check and fix errors.</li>
</ul>
https://practicepython.org/solution/2017/02/03/33-birthday-dictionaries-solutions33 Birthday Dictionaries Solutions2017-02-03T00:00:00+00:002017-02-03T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>For this exercise, we will keep track of when our friend’s birthdays are, and be able to find that information based on their name. Create a dictionary (in your file) of names and birthdays. When you run your program it should ask the user to enter a name, and return the birthday of that person back to them. The interaction should look something like this:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon">>>> Welcome to the birthday dictionary. We know the birthdays of:
Albert Einstein
Benjamin Franklin
Ada Lovelace
>>> Who's birthday do you want to look up?
Benjamin Franklin
>>> Benjamin Franklin's birthday is 01/17/1706.</code></pre></figure>
<h2 id="sample-solution">Sample solution</h2>
<p>One reader does the basics:</p>
<script src="https://gist.github.com/Dimithrandir/75b943f35297a0708a9393d02dfe2121.js"></script>
<p>And here is another reader submission:</p>
<script src="https://gist.github.com/nhyy24/5efa95d627902eba38dbfd1e6f853340.js"></script>
https://practicepython.org/books-for-learnersBooks for learning Python and Programming2017-01-30T00:00:00+00:002017-01-30T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Some people learn better with a reference book in hand. Here are a few of my recommendations for books - some are specifically for learning Python and others are for learning programming in general. These book recommendations are on the <a href="/resources-for-learners">resources for learners</a> page as well.</p>
<!--more-->
<h2 id="learning-python">Learning Python</h2>
<p>The books here are rated from more beginner-skewed to more advanced as the list goes on. I’ve even added my own chili rating to each book!</p>
<table>
<tbody>
<tr>
<td><a target="_blank" href="https://www.amazon.com/gp/product/1593275994/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1593275994&linkCode=as2&tag=practicepytho-20&linkId=dca583cb34a2e0df1172712722f3c0e1"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1593275994&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=practicepytho-20" /></a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=am2&o=1&a=1593275994" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="http://amzn.to/2j6UNsR"><strong>Automate the Boring Stuff with Python</strong> by Al Sweigart</a> definitely has the best title in the business. The style of the book is about what Python can do for you - emphasis on Python tools that can analyze websites, make API calls, and generally automate boring stuff. The emphasis is on Python 3 and on tools like regular expressions and web requests. The explanations are thorough and step-by-step, getting harder through the book. For those looking to get motivated by the ways Python can help you on a daily basis without investing years of study, this is a book to take a look at. I also recommend the <a href="http://click.linksynergy.com/fs-bin/click?id=xcNOXHETw7Y&offerid=323058.3099&type=3&subid=0" target="_blank">Automate the Boring Stuff Udemy course</a> if you are more of a visual and auditory learner - it contains the same content in a video course format.</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><a href="https://www.amazon.com/Learn-Python-Hard-Way-Introduction/dp/0134692888?crid=2AHCB5K6PSX7R&keywords=learn+python+the+hard+way&qid=1644688912&sprefix=learn+python+the+hard+way%2Caps%2C92&sr=8-1&linkCode=li2&tag=practicepytho-20&linkId=dbd5fc1cb7212bc882243f3be9e922f8&language=en_US&ref_=as_li_ss_il" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=0134692888&Format=_SL160_&ID=AsinImage&MarketPlace=US&ServiceVersion=20070822&WS=1&tag=practicepytho-20&language=en_US" /></a><img src="https://ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&language=en_US&l=li2&o=1&a=0134692888" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="https://amzn.to/34x7tSG"><strong>Learn Python 3 The Hard Way</strong> by Zed Shaw</a> is one of the most popular books about learning Python out there. The book goes through concepts important to Python one by one and in great detail. Yes, it is called Learn Python the Hard Way, so the exercises and concepts are grouped together in an unconventional order. The emphasis is on diving in and exploring Python with some basic guidance. There is even a free version of the <a href="https://learnpythonthehardway.org/book/">book online</a>, if that suits you better! There are many editions of this book, but I recommend going straight to the Python 3 latest version! If you prefer reading on Kindle, there’s <a href="https://amzn.to/3LsXPAY">that option too</a>.</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><a target="_blank" href="https://www.amazon.com/gp/product/0134034287/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134034287&linkCode=as2&tag=practicepytho-20&linkId=7668555a401fe5a88644e3cd71805bf5"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=0134034287&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=practicepytho-20" /></a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=am2&o=1&a=0134034287" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="http://amzn.to/2kbmRtC"><strong>Effective Python</strong> by Brett Slatkin</a> is a more advanced book framed in the style of best practices. When you learn to code, you should learn the right way through a series of best practices that are widely used and generally applicable. The style is easy to read, and covers all the major areas of Python development and programming lifecycles. The code examples are helpful and informative as well.</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><a target="_blank" href="https://www.amazon.com/gp/product/1593276036/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1593276036&linkCode=as2&tag=practicepytho-20&linkId=213f202bab70181c22f66db2aeeef1e3"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1593276036&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=practicepytho-20" /></a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=am2&o=1&a=1593276036" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important; float: left" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="http://amzn.to/2j6WSEM"><strong>Python Crash Course</strong> by Eric Matthes</a> approaches learning and teaching Python with the same philosophy as I do - that learning by doing is strictly better than reading. He goes from basics to larger-scale projects like webapps with Python and Python frameworks. The material is well-explained, and gets harder as you get farther along in the book. But all the while, everything is explained in a way that is easy to digest.</td>
</tr>
</tbody>
</table>
<p>Another way to read books is by <a target="_blank" href="https://www.amazon.com/associates/AppDownload?program=1&ref_=assoc_tag_ph_1402131685749&_encoding=UTF8&camp=1789&creative=9325&linkCode=pf4&tag=practicepytho-20&linkId=41478da2293a02765d9c15503e9b8515">Downloading the free Kindle App</a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=pf4&o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> to sync your progress from the computer to your phone.</p>
<p>If you have any favorites, let me know in the comments!</p>
https://practicepython.org/exercise/2017/01/24/33-birthday-dictionaries33 Birthday Dictionaries2017-01-24T00:00:00+00:002017-01-24T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>For this exercise, we will keep track of when our friend’s birthdays are, and be able to find that information based on their name. Create a dictionary (in your file) of names and birthdays. When you run your program it should ask the user to enter a name, and return the birthday of that person back to them. The interaction should look something like this:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon">>>> Welcome to the birthday dictionary. We know the birthdays of:
Albert Einstein
Benjamin Franklin
Ada Lovelace
>>> Who's birthday do you want to look up?
Benjamin Franklin
>>> Benjamin Franklin's birthday is 01/17/1706.</code></pre></figure>
<p>Happy coding!</p>
<h2 id="discussion-topics">Discussion topics</h2>
<ol>
<li>Dictionaries</li>
<li>String formatting, briefly</li>
</ol>
<h3 id="dictionaries">Dictionaries</h3>
<p>We covered dictionaries in <a href="/exercise/2014/12/06/22-read-from-file.html">a previous exercise</a>, but it’s been long enough that we will review them here and add a few more notes.</p>
<h4 id="quick-review">Quick review</h4>
<p>The main topic for this week is the concept of a <em>dictionary</em>. In Python they are called dictionaries, but in other languages they may be called <em>maps</em> or <em>hashmaps</em>. The concept is the same: it is a way to use a <em>key</em> to access some <em>value</em>. It is mapping one set of data (the keys) to another set of data (the values). The only way to access the <em>value</em> part of the dictionary is to use the <em>key</em>.</p>
<p>As an example, grocery store systems can store the prices for various items by using a dictionary. In Python, it would look something like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">price_dictionary</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"banana"</span><span class="p">:</span> <span class="mf">1.50</span><span class="p">,</span>
<span class="s">"avocado"</span><span class="p">:</span> <span class="mf">0.99</span><span class="p">,</span>
<span class="s">"heirloom tomato"</span><span class="p">:</span> <span class="mf">0.89</span><span class="p">,</span>
<span class="s">"cherry tomato pack"</span><span class="p">:</span> <span class="mf">3.00</span>
<span class="p">}</span></code></pre></figure>
<p>You specify the dictionary between the <code class="language-plaintext highlighter-rouge">{}</code>. Key / value pairs are specified as list (separated by commas). The <em>key</em> is on the left side, and the <em>value</em> is on the right side. Notice how I split up the dictionary definition on multiple lines - I did that just for convenience. You can also write the dictionary on the entire line, but it is hard to read (and it probably even goes off your browser window screen):</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">price_dictionary</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"banana"</span><span class="p">:</span> <span class="mf">1.50</span><span class="p">,</span> <span class="s">"avocado"</span><span class="p">:</span> <span class="mf">0.99</span><span class="p">,</span> <span class="s">"heirloom tomato"</span><span class="p">:</span> <span class="mf">0.89</span><span class="p">,</span> <span class="s">"cherry tomato pack"</span><span class="p">:</span> <span class="mf">3.00</span><span class="p">}</span></code></pre></figure>
<p>Now that we have the dictionary, we can query it (ask it) for the values associated with each key (for the prices associated with each food). We do that using brackets (<code class="language-plaintext highlighter-rouge">[]</code>). For example, to get the price of a banana:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">[</span><span class="s">"banana"</span><span class="p">])</span>
<span class="mf">1.50</span></code></pre></figure>
<p>To get a list of all the keys, use the <code class="language-plaintext highlighter-rouge">.keys()</code> method:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">.</span><span class="n">keys</span><span class="p">())</span>
<span class="p">[</span><span class="s">"banana"</span><span class="p">,</span> <span class="s">"avocado"</span><span class="p">,</span> <span class="s">"heirloom tomato"</span><span class="p">,</span> <span class="s">"cherry tomato pack"</span><span class="p">]</span></code></pre></figure>
<p>We have created our dictionary with many items in it, but we can also add items to it one by one. It is almost like accessing an element in the dictionary, except instead of using the element, we assign something to it.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[</span><span class="s">"granny smith apple"</span><span class="p">]</span> <span class="o">=</span> <span class="mf">0.49</span>
<span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[</span><span class="s">"red delicious apple"</span><span class="p">]</span> <span class="o">=</span> <span class="mf">0.35</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">[</span><span class="s">"granny smith apple"</span><span class="p">])</span>
<span class="mf">0.49</span></code></pre></figure>
<p>Not all key / value pairs have to be the same. You can do something like:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[</span><span class="s">"dog food"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"only at Petco"</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">[</span><span class="s">"dog food"</span><span class="p">])</span>
<span class="n">only</span> <span class="n">at</span> <span class="n">Petco</span></code></pre></figure>
<p>Of course, this can get messy quickly, so be careful!</p>
<h4 id="more-on-dictionary-keys">More on dictionary keys</h4>
<p>Dictionary keys must be unique. If you try to add an element to your dictionary with the same key, it will overwrite the value previously at that key:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">[</span><span class="s">"dog food"</span><span class="p">])</span>
<span class="n">only</span> <span class="n">at</span> <span class="n">Petco</span>
<span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[</span><span class="s">"dog food"</span><span class="p">]</span> <span class="o">=</span> <span class="mf">10.99</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">[</span><span class="s">"dog food"</span><span class="p">])</span>
<span class="mf">10.99</span></code></pre></figure>
<p>If you try to ask the dictionary for a key that doesn’t exist, it will throw a <code class="language-plaintext highlighter-rouge">KeyError</code> in your console, or your program will crash:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[</span><span class="s">"lemon"</span><span class="p">]</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">KeyError</span><span class="p">:</span> <span class="s">'lemon'</span></code></pre></figure>
<p>We will talk about how to “catch” errors in later exercises, but for now, there is another way to make sure you don’t throw an error. Instead of accessing elements in a dictionary with the <code class="language-plaintext highlighter-rouge">[]</code> notation, you can instead use the <code class="language-plaintext highlighter-rouge">.get()</code> method. As the second argument to <code class="language-plaintext highlighter-rouge">.get()</code>, you write down what the <em>default value</em> is for the dictionary: if there is no key like the one you wanted, what the dictionary should return:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"banana"</span><span class="p">,</span> <span class="s">"no food like this"</span><span class="p">))</span>
<span class="mf">1.50</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"lemon"</span><span class="p">,</span> <span class="s">"no food like this"</span><span class="p">))</span>
<span class="n">no</span> <span class="n">food</span> <span class="n">like</span> <span class="n">this</span></code></pre></figure>
<p>This can be a helpful way of avoiding causing your program to crash.</p>
<p>Not all Python objects can be keys to a dictionary. For something to be a key in a dictionary, it must be <em>immutable</em>. Basically, it means that you can’t change that variable somewhere else. So for example, numbers and strings can be keys in a dictionary, but lists cannot. Because you can <code class="language-plaintext highlighter-rouge">.append()</code> to a list, it cannot be a key in your dictionary. Lists can be values, just not keys:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]]</span> <span class="o">=</span> <span class="s">"new food"</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">TypeError</span><span class="p">:</span> <span class="n">unhashable</span> <span class="nb">type</span><span class="p">:</span> <span class="s">'list'</span>
<span class="o">>>></span> <span class="n">price_dictionary</span><span class="p">[</span><span class="s">"lettuce"</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mf">1.50</span><span class="p">,</span> <span class="mf">3.50</span><span class="p">]</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">price_dictionary</span><span class="p">[</span><span class="s">"lettuce"</span><span class="p">])</span>
<span class="p">[</span><span class="mf">1.50</span><span class="p">,</span> <span class="mf">3.50</span><span class="p">]</span></code></pre></figure>
<p>Lastly, if we want to check if a particular key is in our dictonary, it is very easy. Just use the <code class="language-plaintext highlighter-rouge">in</code> keyword:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="s">"lemon"</span> <span class="ow">in</span> <span class="n">price_dictionary</span>
<span class="bp">False</span>
<span class="o">>>></span> <span class="s">"banana"</span> <span class="ow">in</span> <span class="n">price_dictionary</span>
<span class="bp">True</span></code></pre></figure>
<p>These checks can be used together with <code class="language-plaintext highlighter-rouge">if</code> statements to make more complex programs.</p>
<h3 id="string-formatting">String formatting</h3>
<p>We’ve talked about strings a lot on this blog:</p>
<ul>
<li>
<a href="(/exercise/2014/01/29/01-character-input.html)">Exercise 1 about printing basic strings</a> <img class="chili" src="/assets/img/chili-liz-20x20.png" />
</li>
<li>
<a href="(/exercise/2014/03/12/06-string-lists.html)">Exercise 6 about turning strings into lists</a> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" />
</li>
<li>
<a href="(/exercise/2014/05/21/15-reverse-word-order.html)">Exercise 15 about where `join` statements are introduced</a> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" />
</li>
</ul>
<p>But we want to introduce one more optional concept for this exercise related to string formatting. There are a number of ways to format strings in Python, so I am just going to show you one quick way for a scenario you find yourself in often while programming.</p>
<p>A common scenario is like this: you want to print both a string and a number in the same line using one <code class="language-plaintext highlighter-rouge">print()</code> statement. You can solve this problem like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="o">>>></span> <span class="n">b</span> <span class="o">=</span> <span class="mi">10</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="s">"my number is "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">+</span> <span class="s">" and his number is "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
<span class="n">my</span> <span class="n">number</span> <span class="ow">is</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">his</span> <span class="n">number</span> <span class="ow">is</span> <span class="mi">10</span></code></pre></figure>
<p>But it gets tedious to use <code class="language-plaintext highlighter-rouge">+</code> and <code class="language-plaintext highlighter-rouge">str()</code>. Instead, you can use the <code class="language-plaintext highlighter-rouge">.format()</code> method to <em>cast</em> (i.e. transform) your number into a string when it gets printed.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="o">>>></span> <span class="n">b</span> <span class="o">=</span> <span class="mi">10</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="s">"my number is {} and his number is {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
<span class="n">my</span> <span class="n">number</span> <span class="ow">is</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">his</span> <span class="n">number</span> <span class="ow">is</span> <span class="mi">10</span></code></pre></figure>
<p>What we are doing is substituting the symbol <code class="language-plaintext highlighter-rouge">{}</code> in the print statement in the string we want to display in the exact place we want the number to go, and use the <code class="language-plaintext highlighter-rouge">.format()</code> to pass variables to the <code class="language-plaintext highlighter-rouge">{}</code> that appear in order. What happens is the variables <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> get converted into strings automatically and injected into our <code class="language-plaintext highlighter-rouge">print</code> statement cleanly. You can do this with floats, lists, dictionaries, or anything else you want to display.</p>
<p>There are a number of different formatting options if you want to get specific about how many decimal points to display, etc., but that is out of the scope of this exercise. If you want to read more about string formatting in Python, you can read about it <a href="https://pyformat.info/">on this helpful website that goes into a great amount of detail</a>.</p>
https://practicepython.org/solution/2017/01/18/32-hangman-solutions32 Hangman Solutions2017-01-18T00:00:00+00:002017-01-18T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>You can start your Python journey anywhere, but to finish this exercise you will have to have finished Parts 1 and 2.</em></p>
<p>In this exercise, we will finish building Hangman. In the game of Hangman, the player only has 6 incorrect guesses (head, body, 2 legs, and 2 arms) before they lose the game.</p>
<p>In Part 1, we loaded a random word list and picked a word from it. In Part 2, we wrote the logic for guessing the letter and displaying that information to the user. In this exercise, we have to put it all together and add logic for handling guesses.</p>
<p>Copy your code from Parts 1 and 2 into a new file as a starting point. Now add the following features:</p>
<ul>
<li>Only let the user guess 6 times, and tell the user how many guesses they have left.</li>
<li>Keep track of the letters the user guessed. If the user guesses a letter they already guessed, don’t penalize them - let them guess again.</li>
</ul>
<p>Optional additions:</p>
<ul>
<li>When the player wins or loses, let them start a new game.</li>
<li>Rather than telling the user <code class="language-plaintext highlighter-rouge">"You have 4 incorrect guesses left"</code>, display some picture art for the Hangman. <em>This is challenging - do the other parts of the exercise first!</em></li>
</ul>
<p>Your solution will be a lot cleaner if you make use of functions to help you!</p>
<h2 id="sample-solution">Sample Solution</h2>
<p>Here is a sample solution from a reader that uses the solutions to Parts 1 and 2, and just puts them on one file:</p>
<script src="https://gist.github.com/anonymous/8ed14085c77095e106c79952be5588cf.js"></script>
<p>And here’s my solution, making more heavy use of functions:</p>
<script src="https://gist.github.com/mprat/ed31902d422353bc572ae8b335150f6c.js"></script>
https://practicepython.org/resources-for-learnersResources for Learning Python and Programming2017-01-15T00:00:00+00:002017-01-15T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Practice Python aims to provide basic exercises for Python learners to discover Python, but it is certainly not a full and comprehensive resource. There are plenty of other resources out there online (both free and not free) that Practice Python recommends.</p>
<!--more-->
<p>This page contains a collection of resources for learners of Python - some are courses, some are books, some are other Python resources. If you have suggestions for what to put on this page, please contact me.</p>
<h1 id="online-courses-for-free">Online courses (for free)</h1>
<p>There are many free resources out there to help you learn Python. Often the downside of free resources is that the usability is not great, or it requires some digging to find some useful content. If you are patient, it can pay off nicely. Some of my favorites:</p>
<ul>
<li>
<p><a href="https://www.codecademy.com/learn/python" target="_blank">Codeacademy</a>. One of my favorite online courses about Python is completely free on Codeacademy. They create great courses (with some sandboxed environments included, so no installation needed!) on a variety of programming languages, and their Python course is great. They will try to upsell you into buying their “premium” course, but I found the free one to be good.</p>
</li>
<li>
<p><a href="http://ocw.mit.edu" target="_blank">OCW (OpenCourseWare) from MIT</a> - this initiative was started in 2001 to make public materials from courses taught at MIT. It is a collection of materials, so you are responsible for pacing yourself, finding the right materials, checking your work, etc. If you are patient enough, you can find the goldmine of materials in the entire site. My biggest beef with this website is the usability - it is really hard to find what kinds of courses you are looking for unless you know the course numbers at MIT. Fortunately, I do. Here are some free reference materials that can provide lecture notes, exercises, and the occasional video:</p>
<ul>
<li><a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-189-a-gentle-introduction-to-programming-using-python-january-iap-2011/" target="_blank">6.189: A Gentle Introduction to Python</a></li>
<li><a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00sc-introduction-to-computer-science-and-programming-spring-2011/" target="_blank">6.00SC: Introduction to Computer Science and Programming</a></li>
<li><a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/" target="_blank">6.00: Introduction to Computer Science and Programming</a></li>
</ul>
</li>
<li>
<p><a href="https://www.edx.org/course/subject/computer-science/python" target="_blank">edX</a> - the natural step up from OCW, edX provides courses to teach you all the subjects of your choice. Universities are incentivized to run an online version of courses offered on college campuses. I’ve linked specifically to the Python course offerings, since they change on a regular basis. If you want more direction (like emails, reminders, exercises mixed in with videos, and a changing set of offerings) together with a college-level and -length course, then edX is a good place to look. They also offer verified certificates for a fee, but I have not personally done a course with verified certificates.</p>
</li>
<li>
<p><a href="imp.i115008.net/Ygaerr" target="_blank">Udacity free introductory Python course</a> - Udacity has a series of online courses, some free and some for a fee, across a variety of topics taught by indutry experts. This course is the free offering for an introductory Python course. It takes 5 weeks and covers the basics in a more hands-on way than is covered here on the blog. If you enjoy it, you might like some of their other <a href="imp.i115008.net/qnjaDg" target="_blank">Python-based course offerings</a>, some of which you have to pay for.</p>
</li>
</ul>
<h1 id="online-courses-for-a-fee">Online courses (for a fee)</h1>
<p>Another way to learn Python and programming is to pay for guided courses. <em>Disclaimer: If you use the links from this page to sign up, this blog will receive a small kickback at no cost to you. Read our <a href="/disclosure.html">full advertising disclosure here</a></em>.</p>
<ul>
<li><a href="https://teamtreehouse.com/techdegree" target="_blank">Treehouse</a> - This company makes easy, digestible courses across a variety of subjects. On top of that, Treehouse as a company has a great work philosophy, and I will happily recommend anything this company produces. To see if you like it, sign up for the free account and check it out!</li>
<li><a href="https://click.linksynergy.com/fs-bin/click?id=xcNOXHETw7Y&offerid=507388.12755&type=3&subid=0" target="_blank">Udemy</a> - With hundreds of course offerings across disciplines you might never even have heard of, Udemy is a platform where subject experts create courses with videos, worksheets, and exercises. One of my favorite courses is called <a href="http://click.linksynergy.com/fs-bin/click?id=xcNOXHETw7Y&offerid=323058.3099&type=3&subid=0" target="_blank">Automate the Boring Stuff with Python</a>, but there are many more on the platform, with even more being added daily.</li>
<li><a href="https://coursera.pxf.io/ZdeBZX" target="_blank">Coursera</a> - Coursera was started by <a href="http://www.andrewng.org/">Andrew Ng</a>, Stanford professor and AI researcher, to deliver high quality online learning to anyone. Coursera offers what they call “specializations” in a variety of disciplines. For beginning Python developers, the <a href="https://coursera.pxf.io/oea07O" target="_blank">“Python for Everybody Specialization”</a> is a set of 6-week courses from the University of Michigan (~2-4 hours per week) to dive into the basics of Python. Of course, there are a wide variety of courses on a range of subjects for you to take for a small fee.</li>
<li><a href="imp.i115008.net/QOQMPx" target="_blank">Udacity Intermediate Python course</a> - Udacity has a series of online courses, some free and some for a fee, across a variety of topics taught by indutry experts. This is an intermediate-level course for Python programming. It is part of the <a href="imp.i115008.net/ZdAMbg">Nanodegree</a> series for a few different disciplines, and is what I would say is a “foundational” course about Python, covering a solid base from which to explore other more specialized areas.</li>
</ul>
<h1 id="online-resources">Online resources</h1>
<ul>
<li><a href="http://pythontutor.com/" target="_blank">PythonTutor</a> - A friend’s website visualizes the line-by-line execution of any Python program you write, directly into the browser! He recently updated the site to include other languages as well.</li>
<li><a href="https://repl.it/languages/python3" target="_blank">repl.it</a> - If you don’t want to download a text editor, you can code Python 3 directly in the cloud! You can share your programs, and there are other supported languages.</li>
</ul>
<h1 id="books">Books</h1>
<h2 id="learning-python">Learning Python</h2>
<p>The books here are rated from more beginner-skewed to more advanced as the list goes on. I’ve even added my own chili rating to each book!</p>
<table>
<tbody>
<tr>
<td><a target="_blank" href="https://www.amazon.com/gp/product/1593275994/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1593275994&linkCode=as2&tag=practicepytho-20&linkId=dca583cb34a2e0df1172712722f3c0e1"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1593275994&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=practicepytho-20" /></a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=am2&o=1&a=1593275994" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="http://amzn.to/2j6UNsR"><strong>Automate the Boring Stuff with Python</strong> by Al Sweigart</a> definitely has the best title in the business. The style of the book is about what Python can do for you - emphasis on Python tools that can analyze websites, make API calls, and generally automate boring stuff. The emphasis is on Python 3 and on tools like regular expressions and web requests. The explanations are thorough and step-by-step, getting harder through the book. For those looking to get motivated by the ways Python can help you on a daily basis without investing years of study, this is a book to take a look at. I also recommend the <a href="http://click.linksynergy.com/fs-bin/click?id=xcNOXHETw7Y&offerid=323058.3099&type=3&subid=0" target="_blank">Automate the Boring Stuff Udemy course</a> if you are more of a visual and auditory learner - it contains the same content in a video course format.</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><a href="https://www.amazon.com/Learn-Python-Hard-Way-Introduction/dp/0134692888?crid=2AHCB5K6PSX7R&keywords=learn+python+the+hard+way&qid=1644688912&sprefix=learn+python+the+hard+way%2Caps%2C92&sr=8-1&linkCode=li2&tag=practicepytho-20&linkId=dbd5fc1cb7212bc882243f3be9e922f8&language=en_US&ref_=as_li_ss_il" target="_blank"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=0134692888&Format=_SL160_&ID=AsinImage&MarketPlace=US&ServiceVersion=20070822&WS=1&tag=practicepytho-20&language=en_US" /></a><img src="https://ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&language=en_US&l=li2&o=1&a=0134692888" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="https://amzn.to/34x7tSG"><strong>Learn Python 3 The Hard Way</strong> by Zed Shaw</a> is one of the most popular books about learning Python out there. The book goes through concepts important to Python one by one and in great detail. Yes, it is called Learn Python the Hard Way, so the exercises and concepts are grouped together in an unconventional order. The emphasis is on diving in and exploring Python with some basic guidance. There is even a free version of the <a href="https://learnpythonthehardway.org/book/">book online</a>, if that suits you better! There are many editions of this book, but I recommend going straight to the Python 3 latest version! If you prefer reading on Kindle, there’s <a href="https://amzn.to/3LsXPAY">that option too</a>.</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><a target="_blank" href="https://www.amazon.com/gp/product/0134034287/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134034287&linkCode=as2&tag=practicepytho-20&linkId=7668555a401fe5a88644e3cd71805bf5"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=0134034287&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=practicepytho-20" /></a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=am2&o=1&a=0134034287" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="http://amzn.to/2kbmRtC"><strong>Effective Python</strong> by Brett Slatkin</a> is a more advanced book framed in the style of best practices. When you learn to code, you should learn the right way through a series of best practices that are widely used and generally applicable. The style is easy to read, and covers all the major areas of Python development and programming lifecycles. The code examples are helpful and informative as well.</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><a target="_blank" href="https://www.amazon.com/gp/product/1593276036/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1593276036&linkCode=as2&tag=practicepytho-20&linkId=213f202bab70181c22f66db2aeeef1e3"><img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1593276036&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=practicepytho-20" /></a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=am2&o=1&a=1593276036" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important; float: left" /></td>
<td> </td>
<td> </td>
<td><img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <a href="http://amzn.to/2j6WSEM"><strong>Python Crash Course</strong> by Eric Matthes</a> approaches learning and teaching Python with the same philosophy as I do - that learning by doing is strictly better than reading. He goes from basics to larger-scale projects like webapps with Python and Python frameworks. The material is well-explained, and gets harder as you get farther along in the book. But all the while, everything is explained in a way that is easy to digest.</td>
</tr>
</tbody>
</table>
<p>Another way to read books is by <a target="_blank" href="https://www.amazon.com/associates/AppDownload?program=1&ref_=assoc_tag_ph_1402131685749&_encoding=UTF8&camp=1789&creative=9325&linkCode=pf4&tag=practicepytho-20&linkId=41478da2293a02765d9c15503e9b8515">Downloading the free Kindle App</a><img src="//ir-na.amazon-adsystem.com/e/ir?t=practicepytho-20&l=pf4&o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> to sync your progress from the computer to your phone.</p>
<p><em>Read our <a href="/disclosure.html">full advertising disclosure</a>.</em></p>
<p>If you have any course or book recommendations, let me know in the comments!</p>
https://practicepython.org/exercise/2017/01/10/32-hangman32 Hangman2017-01-10T00:00:00+00:002017-01-10T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In this exercise, we will finish building Hangman. In the game of Hangman, the player only has 6 incorrect guesses (head, body, 2 legs, and 2 arms) before they lose the game.</p>
<p>In Part 1, we loaded a random word list and picked a word from it. In Part 2, we wrote the logic for guessing the letter and displaying that information to the user. In this exercise, we have to put it all together and add logic for handling guesses.</p>
<p>Copy your code from Parts 1 and 2 into a new file as a starting point. Now add the following features:</p>
<ul>
<li>Only let the user guess 6 times, and tell the user how many guesses they have left.</li>
<li>Keep track of the letters the user guessed. If the user guesses a letter they already guessed, don’t penalize them - let them guess again.</li>
</ul>
<p>Optional additions:</p>
<ul>
<li>When the player wins or loses, let them start a new game.</li>
<li>Rather than telling the user <code class="language-plaintext highlighter-rouge">"You have 4 incorrect guesses left"</code>, display some picture art for the Hangman. <em>This is challenging - do the other parts of the exercise first!</em></li>
</ul>
<p>Your solution will be a lot cleaner if you make use of functions to help you!</p>
<h2 id="concepts">Concepts</h2>
<ul>
<li>Sets</li>
<li>Code organization</li>
</ul>
<h3 id="sets">Sets</h3>
<p>We already discussed sets <a href="/exercise/2014/05/15/14-list-remove-duplicates.html">in Exercise 14</a>, but here is a brief summary:</p>
<ul>
<li>Sets, like lists, store a collection of items</li>
<li>The collection of items in a set are unique. There cannot be any repeated elements.</li>
</ul>
<p>The only “gotcha” is that you cannot have a set of lists - each element in the set must be <a href="https://docs.python.org/3.6/glossary.html#term-hashable">hashable</a>. Basically this means you can’t have elements that can change in a set, so the objects in your set should be integers or strings. The reason and distinction are not super important; the most important thing to know is that sets are most useful when you want a set of integers or strings, rather than a set of lists.</p>
<p>In Python:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">my_list</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">]</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">my_set</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">}</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_set</span><span class="p">)</span>
<span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">}</span></code></pre></figure>
<p>To add elements to a set, use the <code class="language-plaintext highlighter-rouge">.add()</code> method:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">my_set</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span> <span class="c1"># makes an empty set
</span><span class="o">>>></span> <span class="n">my_set</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># adds the number 5
</span><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_set</span><span class="p">)</span>
<span class="p">{</span><span class="mi">5</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">my_set</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">"Michele"</span><span class="p">)</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_set</span><span class="p">)</span>
<span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="s">"Michele"</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">my_set</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_set</span><span class="p">)</span>
<span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="s">"Michele"</span><span class="p">}</span></code></pre></figure>
<p>The advantage of sets is that all the elements in it are unique. This makes it very easy to check whether an element is already in the set. All you need to do is ask <code class="language-plaintext highlighter-rouge">elem in my_set</code>:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">my_set</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">}</span>
<span class="o">>>></span> <span class="mi">1</span> <span class="ow">in</span> <span class="n">my_set</span>
<span class="bp">True</span>
<span class="o">>>></span> <span class="mi">4</span> <span class="ow">in</span> <span class="n">my_set</span>
<span class="bp">False</span></code></pre></figure>
<p>And this check is very fast - much faster than doing the same <code class="language-plaintext highlighter-rouge">in</code> check with a list. (<em>The reason it is fast is a concept called hashing, which you can read about in detail <a href="http://stackoverflow.com/questions/3949310/how-is-set-implemented">in this StackOverflow post</a>.</em>)</p>
<h3 id="code-organization">Code organization</h3>
<p>We briefly discussed some tips on working with lots of code in <a href="/exercise/2016/08/03/29-tic-tac-toe-game.html">Exercise 29</a>, and I’ll add a few more here:</p>
<ul>
<li>If you don’t like your code from Parts 1 and 2, just take any of the code from the <a href="/solution/2016/10/15/30-pick-word-solutions.html">solution to Part 1</a> or the <a href="/solution/2017/01/08/31-guess-letters-solutions.html">solution to Part 2</a> to start. Just because you wrote some code before, doesn’t mean you are locked in forever!</li>
<li>Any piece of your code that is used more than once, put it into a function. We did a long discussion of functions in <a href="/exercise/2014/04/16/11-check-primality-functions.html">Exercise 11</a>, if you want a review.</li>
<li>Your functions should be small and easy to understand - think of it as a 3-year-old child; if you ask a 3-year-old to do too many things, they will get confused and not do exactly what you asked.</li>
</ul>
<p>If you have any other code organization tips, leave them in the comments, would love to get a good discussion going.</p>
https://practicepython.org/solution/2017/01/08/31-guess-letters-solutions31 Guess Letters Solutions2017-01-08T00:00:00+00:002017-01-08T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Let’s continue building Hangman. In the game of Hangman, a clue word is given by the program that the player has to guess, letter by letter. The player guesses one letter at a time until the entire word has been guessed. (In the actual game, the player can only guess 6 letters incorrectly before losing).</p>
<p>Let’s say the word the player has to guess is “EVAPORATE”. For this exercise, write the logic that asks a player to guess a letter and displays letters in the clue word that were guessed correctly. For now, let the player guess an infinite number of times until they get the entire word. As a bonus, keep track of the letters the player guessed and display a different message if the player tries to guess that letter again. Remember to stop the game when all the letters have been guessed correctly! Don’t worry about choosing a word randomly or keeping track of the number of guesses the player has remaining - we will deal with those in a future exercise.</p>
<p>An example interaction can look like this:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon">>>> Welcome to Hangman!
_ _ _ _ _ _ _ _ _
>>> Guess your letter: S
Incorrect!
>>> Guess your letter: E
E _ _ _ _ _ _ _ E
...</code></pre></figure>
<p>And so on, until the player gets the word.</p>
<h2 id="sample-solution">Sample solution</h2>
<p>To write the logic of our Hangman game, we need a few components:</p>
<ol>
<li>A way to store the word in play</li>
<li>Keep track of which letters in the word have already been guessed</li>
<li>Ask the user for a letter and display the results</li>
</ol>
<p>As a bonus, we can add the component of displaying a different message if the user has already guessed that letter.</p>
<p>Things to keep in mind:</p>
<ul>
<li>Upper-case letters and lower-case letters are not equal! When you do <code class="language-plaintext highlighter-rouge">'a' == 'A'</code> in Python, the result will be FALSE! So make sure to do all your operations in either lowercase or uppercase.</li>
<li>It is much faster to check whether an element is in a set than a list. This is not important for the correctness of your program, but it is a good thing to keep in mind for when your programs become more complex.</li>
</ul>
<p>Here is one sample solution:</p>
<script src="https://gist.github.com/anonymous/c39e3b9db1764a3a119f6dc90905c2b2.js"></script>
<p>The only thing I would change here is on line 9, change <code class="language-plaintext highlighter-rouge">lstGuessed</code> to a <code class="language-plaintext highlighter-rouge">set()</code>, so that on line 12, the <code class="language-plaintext highlighter-rouge">in</code> check will be very fast.</p>
<p>As always, play on!</p>
https://practicepython.org/exercise/2017/01/02/31-guess-letters31 Guess Letters2017-01-02T00:00:00+00:002017-01-02T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Let’s continue building Hangman. In the game of Hangman, a clue word is given by the program that the player has to guess, letter by letter. The player guesses one letter at a time until the entire word has been guessed. (In the actual game, the player can only guess 6 letters incorrectly before losing).</p>
<p>Let’s say the word the player has to guess is “EVAPORATE”. For this exercise, write the logic that asks a player to guess a letter and displays letters in the clue word that were guessed correctly. For now, let the player guess an infinite number of times until they get the entire word. As a bonus, keep track of the letters the player guessed and display a different message if the player tries to guess that letter again. Remember to stop the game when all the letters have been guessed correctly! Don’t worry about choosing a word randomly or keeping track of the number of guesses the player has remaining - we will deal with those in a future exercise.</p>
<p>An example interaction can look like this:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon">>>> Welcome to Hangman!
_ _ _ _ _ _ _ _ _
>>> Guess your letter: S
Incorrect!
>>> Guess your letter: E
E _ _ _ _ _ _ _ E
...</code></pre></figure>
<p>And so on, until the player gets the word.</p>
https://practicepython.org/blog/2016/12/20/instagram-filters-pythonInstagram Filters in 15 Lines of Python2016-12-20T00:00:00+00:002016-12-20T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>This post is written by Michele Pratusevich.</em>
I love the Python programming language, and I love computational photography. This post describes how to make (almost) any Instagram filter with about 15 lines of Python, using the (now-defunct) Gotham Instagram filter as a case study. I presented this at a lighting talk at the Boston Python Meetup on December 20th, and you can find my slides <a href="https://mprat.org/assets/python-instagram-filters-slides.slides.html">on my personal site</a>.</p>
<!-- more -->
<p>First we will go through some basic setup and dependencies, then we’ll build the elements of an Instagram filter, and finally at the end we will build the filter itself.</p>
<h2 id="dependencies">Dependencies</h2>
<p>There are a number of libraries that let you do image processing in Python, but the ones I use in this post are: <code class="language-plaintext highlighter-rouge">matplotlib</code> for plotting images, <code class="language-plaintext highlighter-rouge">numpy</code> for processing lits of floats, and <code class="language-plaintext highlighter-rouge">scikit-image</code> for loading the image. The code I show here is meant for a Python script, bit you can extend the code into a <code class="language-plaintext highlighter-rouge">jupyter notebook</code> to make it interactive. That will be the subject of a subsequent post.</p>
<p>Let’s set up our dependencies:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">import</span> <span class="nn">skimage</span>
<span class="kn">from</span> <span class="nn">skimage</span> <span class="kn">import</span> <span class="n">io</span>
<span class="kn">from</span> <span class="nn">skimage</span> <span class="kn">import</span> <span class="n">filters</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span></code></pre></figure>
<p>I also personally like to (when viewing images), set the default axes in <code class="language-plaintext highlighter-rouge">matplotlib</code> to not show any labels or tick marks on the x and y axes:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">matplotlib</span>
<span class="n">matplotlib</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">'xtick.major.size'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">matplotlib</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">'ytick.major.size'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">matplotlib</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">'xtick.labelsize'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">matplotlib</span><span class="p">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s">'ytick.labelsize'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span></code></pre></figure>
<p>All the images I generated in this post were made with <code class="language-plaintext highlighter-rouge">matplotlib</code> using these settings.</p>
<h2 id="load-an-image">Load an image</h2>
<p>Let’s import a picture (I am using a picture I took in downtown Seattle that is hosted <a href="/assets/imgs/skyline.jpg">here</a> that you are welcome to use as well). We will import it using <code class="language-plaintext highlighter-rouge">scikit-image</code>, but we still have to be careful. Most images are formatted in <code class="language-plaintext highlighter-rouge">uint8</code>, which means that every pixel color is an integer from 0 to 255. For example, red is (255, 0, 0) and blue is (0, 0, 255). When you are doing arithmetic on images (like dividing all pixels by some value), you want your pixels to be represented as decimal numbers or floats. So when we import our image, we will both read the image and automatically convert it to storing pixel values as floats in the range of (0, 1).</p>
<p>For this code to work, make sure the <code class="language-plaintext highlighter-rouge">skyline.jpg</code> image is in the same folder as your Python script. If it is not in the same folder, just put the full or relative path of the file into the <code class="language-plaintext highlighter-rouge">imread</code> function.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">original_image</span> <span class="o">=</span> <span class="n">skimage</span><span class="p">.</span><span class="n">img_as_float</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">imread</span><span class="p">(</span><span class="s">"skyline.jpg"</span><span class="p">))</span></code></pre></figure>
<p>If you want to see the image, you can use <code class="language-plaintext highlighter-rouge">matplotlib</code>:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">plt</span><span class="p">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">original_image</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span></code></pre></figure>
<p>You should see this image. It’s the one we will be working with for the rest of this post.</p>
<figure>
<img src="/assets/imgs/skyline.jpg" alt="The original image" class="post-img" style="width: 50%" />
<figcaption>Fig 1. - The original image that will be Insta-filtered. It could use some sprucing up.</figcaption>
</figure>
<h2 id="basic-ingredients">Basic ingredients</h2>
<p>There are two basic ingredients to any Instagram filter:</p>
<ol>
<li>Sharpening</li>
<li>Adjusting channels by linear interpolation</li>
</ol>
<p>We will go through both image manipulations and ultimately put together the Gotham filter using these two elements.</p>
<h2 id="sharpening-and-blurring">Sharpening and blurring</h2>
<p>The first element to any Instagram filter is sharpening or blurring an image.</p>
<p>Sharpening an image is the same as removing a blurred version of the image from itself. This is exactly how we will implement sharpening an image. First, blur an image using a Gaussian blur, then subtract a portion of the Gaussian blur from the original image. Presto, a sharper image!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">sharpen</span><span class="p">(</span><span class="n">image</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">sigma</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span>
<span class="n">blurred</span> <span class="o">=</span> <span class="n">filters</span><span class="p">.</span><span class="n">gaussian</span><span class="p">(</span><span class="n">image</span><span class="p">,</span> <span class="n">sigma</span><span class="o">=</span><span class="n">sigma</span><span class="p">,</span> <span class="n">multichannel</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">sharper</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">image</span> <span class="o">*</span> <span class="n">a</span> <span class="o">-</span> <span class="n">blurred</span> <span class="o">*</span> <span class="n">b</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">)</span>
<span class="k">return</span> <span class="n">sharper</span></code></pre></figure>
<p>Our sharpen function takes 4 arguments: the image, two constants, <code class="language-plaintext highlighter-rouge">a</code> being the amount to multiply the original image by, and <code class="language-plaintext highlighter-rouge">b</code> being the amount to multiply the blurred image by, and an optional <code class="language-plaintext highlighter-rouge">sigma</code> value for our Gaussian. Higher values of <code class="language-plaintext highlighter-rouge">sigma</code> will cause more radical blurring. <code class="language-plaintext highlighter-rouge">scikit-image</code> implements a Gaussian filter for us, so no need to remember those pesky formulas. Also, we need to make sure to clip our image to the range 0 to 1.0, so we don’t have any strange artifacts - this is what the <code class="language-plaintext highlighter-rouge">np.clip</code> portion of the code above does. So, to sharpen our original image, we just do the following:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">sharper</span> <span class="o">=</span> <span class="n">sharpen</span><span class="p">(</span><span class="n">original_image</span><span class="p">,</span> <span class="mf">1.3</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">)</span></code></pre></figure>
<figure>
<img src="/assets/imgs/skyline_sharper.jpg" alt="The original image and the sharper image" class="post-img" />
<figcaption>Fig 2. - The original image (left) and the sharpened image (right).</figcaption>
</figure>
<p>We can use the <code class="language-plaintext highlighter-rouge">sharpen</code> function above to also blur the image. What happens is that we are already computing a blurred image in the function to subtract from the original image. So to blur the image, all we have to do is call <code class="language-plaintext highlighter-rouge">sharpen</code> with <code class="language-plaintext highlighter-rouge">a = 0</code> and a negative value of <code class="language-plaintext highlighter-rouge">b</code>:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">blurred</span> <span class="o">=</span> <span class="n">sharpen</span><span class="p">(</span><span class="n">original_image</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.0</span><span class="p">)</span></code></pre></figure>
<figure>
<img src="/assets/imgs/skyline_blurred.jpg" alt="The original image and the blurred image" class="post-img" />
<figcaption>Fig 3. - The original image (left) and the blurred image (right).</figcaption>
</figure>
<h2 id="adjusting-channels-by-linear-interpolation">Adjusting channels by linear interpolation</h2>
<p>The second element to any Instagram filter is the ability to adjust any image channel by linear interpolation. If you have ever used Adobe Lightroom, Photoshop, or Gimp, you will have seen the histogram of color values:</p>
<figure>
<img src="/assets/imgs/gimp_hist.jpg" alt="A gimp color histogram" style="margin: auto; display: block;" />
<figcaption>Fig 4. - The Gimp red color histogram.</figcaption>
</figure>
<p>What we want to be able to do is manipulate the an individual color channel by stretching or squeezing particular color ranges. As we mentioned before, there are 255 different values a single pixel can take - all the red pixels have a value between 0 and 255. Same for the green and blue channels. What we want to do is be able to say something like “let’s take all the strong blues and make them even bluer, but in a way that looks natural.” The way we can do this in practice is to linearly interpolate a range of values in the histogram above to a different range. That way, the color changes will look “natural”, but they will be modified.</p>
<p>For example, Gimp does this in a more sophisticated way by using spline interpolation:</p>
<figure>
<img src="/assets/imgs/gimp_hist2.jpg" alt="A gimp color histogram adjusted" class="post-img" />
<figcaption>Fig 5. - The Gimp red color histogram adjusted.</figcaption>
</figure>
<p>To make our code simpler, we will just use linear interpolation between various points on the curve. This way, we can specify the interpolation we want with a series of values. The one thing to keep in mind is that we are manipulating images in the float range from 0.0 to 1.0, but when our image gets displayed or written to a file, they will be bucketed in the range 0 to 255. Our code looks like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">channel_adjust</span><span class="p">(</span><span class="n">channel</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="c1"># flatten
</span> <span class="n">orig_size</span> <span class="o">=</span> <span class="n">channel</span><span class="p">.</span><span class="n">shape</span>
<span class="n">flat_channel</span> <span class="o">=</span> <span class="n">channel</span><span class="p">.</span><span class="n">flatten</span><span class="p">()</span>
<span class="n">adjusted</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">interp</span><span class="p">(</span>
<span class="n">flat_channel</span><span class="p">,</span>
<span class="n">np</span><span class="p">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)),</span>
<span class="n">values</span><span class="p">)</span>
<span class="c1"># put back into image form
</span> <span class="k">return</span> <span class="n">adjusted</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="n">orig_size</span><span class="p">)</span></code></pre></figure>
<p>We will take in a single image channel (either the red, blue, or green channel), and specify a list of float values that will serve as our interpolation points. The channel will then be broken into that many segments, and the points originally from those segments will be linearly interpolated according to the values. For example, if I specify the <code class="language-plaintext highlighter-rouge">values</code> as [0, 0.05, 0.5, 0.95, 1.0], the values from [0, 1.0] will be broken into 5 equal buckets: [0, 0.25, 0.5, 0.75, 1.0], and each segment of values will be mapped to the output values. So the range [0, 0.25] will be re-mapped linearly to the range [0, 0.05]. The range [0.25, 0.5] will be mapped to the range [0.05, 0.5], and so on.</p>
<p>A visualization of what the code is doing is shown below:</p>
<figure>
<img src="/assets/imgs/linear_interp_channel.png" alt="Linear interpolation on a channel visualization" class="post-img" style="width: 50%" />
<figcaption>Fig 6. - A visualization of linear interpolation on a channel.</figcaption>
</figure>
<p>What this does to a real image channel (say the red channel, to mimic the output of Figure 5 above) looks like this, using the values [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.865, 0.875, 1]:</p>
<figure>
<img src="/assets/imgs/redder_sky.jpg" alt="Linear interpolation on a channel visualization" class="post-img" />
<figcaption>Fig 7. - A visualization of linear interpolation on a channel.</figcaption>
</figure>
<p>So what we have is a way to manipulate individual image channels to modify the color composition of any image.</p>
<h2 id="a-few-helper-functions">A few helper functions</h2>
<p>To finish off our Instagram filters, we just need two helper functions:</p>
<ol>
<li>A function to split an image into image channels (red, green, blue)</li>
<li>A function to merge the image channels back into an image</li>
</ol>
<p>To split an image into red, green, and blue channels, just take the first, second, and third elements of the image respectively. We are lucky that <code class="language-plaintext highlighter-rouge">scikit-image</code> reads images in the standard “RGB” image format, where the first channel is red, the second green, and the third blue.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">split_image_into_channels</span><span class="p">(</span><span class="n">image</span><span class="p">):</span>
<span class="n">red_channel</span> <span class="o">=</span> <span class="n">image</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">0</span><span class="p">]</span>
<span class="n">green_channel</span> <span class="o">=</span> <span class="n">image</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">1</span><span class="p">]</span>
<span class="n">blue_channel</span> <span class="o">=</span> <span class="n">image</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">2</span><span class="p">]</span>
<span class="k">return</span> <span class="n">red_channel</span><span class="p">,</span> <span class="n">green_channel</span><span class="p">,</span> <span class="n">blue_channel</span></code></pre></figure>
<p>And now to merge the channels back into an image:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">merge_channels</span><span class="p">(</span><span class="n">red_channel</span><span class="p">,</span> <span class="n">green_channel</span><span class="p">,</span> <span class="n">blue_channel</span><span class="p">):</span>
<span class="k">return</span> <span class="n">np</span><span class="p">.</span><span class="n">stack</span><span class="p">([</span><span class="n">red_channel</span><span class="p">,</span> <span class="n">green_channel</span><span class="p">,</span> <span class="n">blue_channel</span><span class="p">],</span> <span class="n">axis</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span></code></pre></figure>
<p>To prove to yourself that this works, you can split, merge, and show the image:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">split_image_into_channels</span><span class="p">(</span><span class="n">original_image</span><span class="p">)</span>
<span class="n">im</span> <span class="o">=</span> <span class="n">merge_channels</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">im</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span></code></pre></figure>
<p>And you should see the original image in Figure 1 back again.</p>
<h2 id="the-gotham-filter">The Gotham filter</h2>
<p>Now let’s put it all together to make the Gotham filter. The Gotham filter is calculated as follows:</p>
<ol>
<li>A mid-tone red contrast boost</li>
<li>Make the blacks a little bluer</li>
<li>A small sharpening</li>
<li>A boost in blue channel for lower mid-tones</li>
<li>A decrease in blue channel for upper mid-tones</li>
</ol>
<p>And we’re off!</p>
<h3 id="step-1">Step 1</h3>
<p>First, split the image into channels for manipulation.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">split_image_into_channels</span><span class="p">(</span><span class="n">original_image</span><span class="p">)</span></code></pre></figure>
<p>Next, we will increase the contrast in the reddish mid-tones by stretching out the red channel.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">r_boost_lower</span> <span class="o">=</span> <span class="n">channel_adjust</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="p">[</span>
<span class="mi">0</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">,</span>
<span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.9</span><span class="p">,</span>
<span class="mf">0.95</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">])</span></code></pre></figure>
<p>You can see the histogram changes:</p>
<figure>
<img src="/assets/imgs/r_boost_hist.jpg" alt="Red channel histogram boost" class="post-img" />
<figcaption>Fig 8. - Step 1 of Gotham filter: red channel mid-tone contrast boost (histogram).</figcaption>
</figure>
<p>And the image changes:</p>
<figure>
<img src="/assets/imgs/r_boost_img.jpg" alt="Red channel contrast boost image" class="post-img" />
<figcaption>Fig 9. - Step 1 of Gotham filter: red channel mid-tone contrast boost (image).</figcaption>
</figure>
<h3 id="step-2">Step 2</h3>
<p>Next, we’ll make the blacks a little bit bluer, by simply adding <code class="language-plaintext highlighter-rouge">0.03</code> to every single black pixel value. This makes everything that is already blue, bluer. We’ll merge the image back together to see where we are at now. We use <code class="language-plaintext highlighter-rouge">np.clip</code> to make sure none of the image pixel values end up outside the allowed image range, so in some cases we are saturating the blue channel.</p>
<figure class="highlight"><pre><code class="language-language" data-lang="language">bluer_blacks = merge_channels(r_boost_lower, g, np.clip(b + 0.03, 0, 1.0))</code></pre></figure>
<figure>
<img src="/assets/imgs/bluer_blacks_img.jpg" alt="Make the blues a little blacker" class="post-img" />
<figcaption>Fig 10. - Step 2 of Gotham filter: make the blacks bluer.</figcaption>
</figure>
<h3 id="step-3">Step 3</h3>
<p>Now let’s sharpen, using the sharpening function we discussed above.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">sharper</span> <span class="o">=</span> <span class="n">sharpen</span><span class="p">(</span><span class="n">bluer_blacks</span><span class="p">,</span> <span class="mf">1.3</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">,</span> <span class="n">sigma</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span></code></pre></figure>
<p>You can see more detail, especially around the edges of the buildings.</p>
<figure>
<img src="/assets/imgs/sharpened_img.jpg" alt="A small sharpening" class="post-img" />
<figcaption>Fig 11. - Step 3 of Gotham filter: a small sharpening.</figcaption>
</figure>
<h3 id="steps-4-and-5">Steps 4 and 5</h3>
<p>Lastly, there are two manipulations on the blue channel we will accomplish with one call to our linear interpolation function. We will increase the blue channel in the lower mid-tones and decrease the blue channel in the upper mid-tones. Thankfully all this requires is clever choosing of the linear interpolation coefficients. Because we’ve changed the image channels by sharpening the image in the previous step, we need to re-split the image into red, green, and blue channels.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">split_image_into_channels</span><span class="p">(</span><span class="n">sharper</span><span class="p">)</span>
<span class="n">b_adjusted</span> <span class="o">=</span> <span class="n">channel_adjust</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">[</span>
<span class="mi">0</span><span class="p">,</span> <span class="mf">0.047</span><span class="p">,</span> <span class="mf">0.118</span><span class="p">,</span> <span class="mf">0.251</span><span class="p">,</span> <span class="mf">0.318</span><span class="p">,</span>
<span class="mf">0.392</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.439</span><span class="p">,</span> <span class="mf">0.475</span><span class="p">,</span>
<span class="mf">0.561</span><span class="p">,</span> <span class="mf">0.58</span><span class="p">,</span> <span class="mf">0.627</span><span class="p">,</span> <span class="mf">0.671</span><span class="p">,</span>
<span class="mf">0.733</span><span class="p">,</span> <span class="mf">0.847</span><span class="p">,</span> <span class="mf">0.925</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span></code></pre></figure>
<p>And you can see the histogram of the blue channel as it is transformed:</p>
<figure>
<img src="/assets/imgs/b_adjusted_hist.jpg" alt="Blue channel manipulations" class="post-img" />
<figcaption>Fig 12. - Steps 4 and 5 of Gotham filter: blue channel manipulations.</figcaption>
</figure>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>All in all, you can make the Gotham Instagram filter with just 15 lines of Python (not including imports):</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="nn">skimage</span>
<span class="kn">from</span> <span class="nn">skimage</span> <span class="kn">import</span> <span class="n">io</span><span class="p">,</span> <span class="n">filters</span>
<span class="k">def</span> <span class="nf">channel_adjust</span><span class="p">(</span><span class="n">channel</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">orig_size</span> <span class="o">=</span> <span class="n">channel</span><span class="p">.</span><span class="n">shape</span>
<span class="n">flat_channel</span> <span class="o">=</span> <span class="n">channel</span><span class="p">.</span><span class="n">flatten</span><span class="p">()</span>
<span class="n">adjusted</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">interp</span><span class="p">(</span><span class="n">flat_channel</span><span class="p">,</span> <span class="n">np</span><span class="p">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)),</span> <span class="n">values</span><span class="p">)</span>
<span class="k">return</span> <span class="n">adjusted</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="n">orig_size</span><span class="p">)</span>
<span class="n">original_image</span> <span class="o">=</span> <span class="n">skimage</span><span class="p">.</span><span class="n">img_as_float</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">imread</span><span class="p">(</span><span class="s">"skyline.jpg"</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">original_image</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">0</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">original_image</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">2</span><span class="p">]</span>
<span class="n">r_boost_lower</span> <span class="o">=</span> <span class="n">channel_adjust</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="p">[</span>
<span class="mi">0</span><span class="p">,</span> <span class="mf">0.05</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">,</span>
<span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.9</span><span class="p">,</span>
<span class="mf">0.95</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">])</span>
<span class="n">b_more</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">b</span> <span class="o">+</span> <span class="mf">0.03</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">)</span>
<span class="n">merged</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">stack</span><span class="p">([</span><span class="n">r_boost_lower</span><span class="p">,</span> <span class="n">original_image</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">b_more</span><span class="p">],</span> <span class="n">axis</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">blurred</span> <span class="o">=</span> <span class="n">filters</span><span class="p">.</span><span class="n">gaussian</span><span class="p">(</span><span class="n">merged</span><span class="p">,</span> <span class="n">sigma</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">multichannel</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">final</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="n">merged</span> <span class="o">*</span> <span class="mf">1.3</span> <span class="o">-</span> <span class="n">blurred</span> <span class="o">*</span> <span class="mf">0.3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">final</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">2</span><span class="p">]</span>
<span class="n">b_adjusted</span> <span class="o">=</span> <span class="n">channel_adjust</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">[</span>
<span class="mi">0</span><span class="p">,</span> <span class="mf">0.047</span><span class="p">,</span> <span class="mf">0.118</span><span class="p">,</span> <span class="mf">0.251</span><span class="p">,</span> <span class="mf">0.318</span><span class="p">,</span>
<span class="mf">0.392</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.439</span><span class="p">,</span> <span class="mf">0.475</span><span class="p">,</span>
<span class="mf">0.561</span><span class="p">,</span> <span class="mf">0.58</span><span class="p">,</span> <span class="mf">0.627</span><span class="p">,</span> <span class="mf">0.671</span><span class="p">,</span>
<span class="mf">0.733</span><span class="p">,</span> <span class="mf">0.847</span><span class="p">,</span> <span class="mf">0.925</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">final</span><span class="p">[:,</span> <span class="p">:,</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">b_adjusted</span></code></pre></figure>
<figure>
<img src="/assets/imgs/gotham.jpg" alt="The Gotham filter" class="post-img" />
<figcaption>Fig 13. - The Gotham Filter.</figcaption>
</figure>
<p>Play around, create your own filters!</p>
<h2 id="references">References</h2>
<p>I took inspiration (and a few linear interpolation values) from <a href="http://www.creativebloq.com/netmag/how-go-beyond-basics-svg-filters-71412280">Michael Mullany’s post at Creative Bloq on how to re-create the Gotham Instagram filter using SVG components</a>. Because I chose to do my filters in Python, I did not use exactly the same techniques as shown in the article.</p>
https://practicepython.org/blog/2016/12/20/blogrollLaunching the Practice Python blog2016-12-20T00:00:00+00:002016-12-20T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Practice Python is doing well with exercises, solutions, comments, etc. But it needs more! So, I have set up a blog section of Practice Python, which will be updated whenever I have something interesting to say about Python!</p>
<!-- more -->
<h2 id="launching-the-blog">Launching the blog</h2>
<p>The bread and butter of Practice Python is exercises and solutions. Once in a while there are topics or discussions I want to share with readers of the site that can’t be formatted in exercise / solution form.</p>
<p>The blog will be updated whenever I have something interesting to say about Python, or if a guest poster has something fun they want to share with the audience of Practice Python.</p>
<p>If you subscribe to the Practice Python RSS feed, email list, or Twitter feed, you will get notified whenever a new blog post has been put up, the same way as exercises and solutions notify you now.</p>
<p>I hope you enjoy it!</p>
https://practicepython.org/solution/2016/10/15/30-pick-word-solutions30 Pick Word Solutions2016-10-15T00:00:00+00:002016-10-15T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In this exercise, the task is to write a function that picks a random word from a list of words from the <a href="http://norvig.com/ngrams/sowpods.txt">SOWPODS dictionary</a>. Download this file and save it in the same directory as your Python code. This file is <a href="https://en.wikipedia.org/wiki/Peter_Norvig">Peter Norvig</a>’s compilation of the dictionary of words used in professional Scrabble tournaments. Each line in the file contains a single word.</p>
<p><em>Hint: use the Python <code class="language-plaintext highlighter-rouge">random</code> library for picking a random word.</em></p>
<h2 id="sample-solution">Sample solution</h2>
<p>To solve this exercise, you need to do three things:</p>
<ol>
<li>Read all the lists of words</li>
<li>Generate a random number</li>
<li>Take that word</li>
</ol>
<p>Here is a sample solution:</p>
<script src="https://gist.github.com/coderunner007/0f9a2bc3c45f70979fba09666ef3dc2e.js"></script>
<p>Here is an alternate approach, with some comments:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="c1"># import the random library
</span> <span class="kn">import</span> <span class="nn">random</span>
<span class="c1"># read all the list of words
</span> <span class="n">words</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'sowpods.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="n">words</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="n">words</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="c1"># generate a random number
</span> <span class="n">random_index</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
<span class="c1"># take the word
</span> <span class="k">print</span><span class="p">(</span><span class="s">"Random word: "</span><span class="p">,</span> <span class="n">words</span><span class="p">[</span><span class="n">random_index</span><span class="p">])</span></code></pre></figure>
<p>There are many solutions to every problem. Enjoy hacking around to find another solution!</p>
https://practicepython.org/exercise/2016/09/24/30-pick-word30 Pick Word2016-09-24T00:00:00+00:002016-09-24T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In this exercise, the task is to write a function that picks a random word from a list of words from the <a href="http://norvig.com/ngrams/sowpods.txt">SOWPODS dictionary</a>. Download this file and save it in the same directory as your Python code. This file is <a href="https://en.wikipedia.org/wiki/Peter_Norvig">Peter Norvig</a>’s compilation of the dictionary of words used in professional Scrabble tournaments. Each line in the file contains a single word.</p>
<p><em>Hint: use the Python <code class="language-plaintext highlighter-rouge">random</code> library for picking a random word.</em></p>
<h3 id="aside-what-is-sowpods">Aside: what is SOWPODS</h3>
<p>SOWPODS is a word list commonly used in word puzzles and games (like Scrabble for example). It is the combination of the Scrabble Player’s Dictionary and the Chamber’s Dictionary. (The history of SOWPODS is quite interesting, I highly recommend reading the <a href="https://en.wikipedia.org/wiki/SOWPODS">Wikipedia article if you are curious</a>.)</p>
<h2 id="previous-exercises-with-similar-concepts">Previous exercises with similar concepts</h2>
<p>In previous exercises, we have covered all the necessary skills needed to complete this exercise. Check out:</p>
<ol>
<li>
<a href="/exercise/2014/12/06/22-read-from-file.html">Exercise 22: read from a file</a> <img class="chili" src="/assets/img/chili-liz-20x20.png" />
</li>
<li>
<a href="/exercise/2014/04/02/09-guessing-game-one.html">Exercise 9: generating a random number</a> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" />
</li>
<li>
<a href="/exercise/2014/02/15/03-list-less-than-ten.html">Exercise 3: accessing an element of a list</a> <img class="chili" src="/assets/img/chili-liz-20x20.png" /> <img class="chili" src="/assets/img/chili-liz-20x20.png" />
</li>
</ol>
<h2 id="brief-concept-review">Brief concept review</h2>
<h3 id="reading-a-file">Reading a file</h3>
<p>The Python way of reading a file from disk is to use the <code class="language-plaintext highlighter-rouge">with</code> construction together with a <code class="language-plaintext highlighter-rouge">while</code> loop:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'filename.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="c1"># do something to the line, for example
</span> <span class="c1"># saving it to disk
</span> <span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"The entire file as been read!"</span><span class="p">)</span></code></pre></figure>
<p>The file <code class="language-plaintext highlighter-rouge">filename.txt</code> should be in the same directory as your Python script.</p>
<p>The idea behind the <code class="language-plaintext highlighter-rouge">with</code> construction is that it isolates any variables defined in the <code class="language-plaintext highlighter-rouge">with</code> line from the rest of your code. When you are dealing with files, this means properly opening and closing the files. The <code class="language-plaintext highlighter-rouge">open</code> line in the <code class="language-plaintext highlighter-rouge">with</code> statement actually does the opening of the file and saves the file object in the variable <code class="language-plaintext highlighter-rouge">f</code>. The <code class="language-plaintext highlighter-rouge">'r'</code> passed into the <code class="language-plaintext highlighter-rouge">open()</code> function tells Python “open the file for reading”. If the <code class="language-plaintext highlighter-rouge">'w'</code> argument is passed instead, Python will interpret this as “open the file and allow writing to it.”</p>
<p>After all the code inside the <code class="language-plaintext highlighter-rouge">with</code> block is finished, the file <code class="language-plaintext highlighter-rouge">f</code> is properly closed by Python. So by the time the program starts executing the <code class="language-plaintext highlighter-rouge">print</code> statement, the file is already closed.</p>
<p>One thing to remember when reading lines from a file in this way is that a line contains a <code class="language-plaintext highlighter-rouge">\n</code>, or a newline character at the end. So before processing the line, it is usually a good idea to use <code class="language-plaintext highlighter-rouge">.strip()</code> to remove the newlines and spaces from the start and end of the lines, like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'filename.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="c1"># do something with the 'line' variable
</span> <span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span></code></pre></figure>
<p>There are many ways of reading lines from files. If for example you want to read all the lines of the file into a list, you can use the following variant:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'filename.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">lines</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readlines</span><span class="p">()</span></code></pre></figure>
<p>At the end of this code, the variable <code class="language-plaintext highlighter-rouge">lines</code> will have all the elements from the file in a Python list.</p>
<p>Here are a few references about opening files, if you would like to read more:</p>
<ul>
<li><a href="https://learnpythonthehardway.org/book/ex15.html">Learn Python the Hard Way page about reading files</a></li>
<li>The Python 3.5 documentation about <a href="https://docs.python.org/3.5/tutorial/inputoutput.html#reading-and-writing-files">reading and writing files</a></li>
</ul>
<h3 id="generating-a-random-number">Generating a random number</h3>
<p>Python’s <code class="language-plaintext highlighter-rouge">random</code> library is used to do operations with random numbers. For a list of the full methods available in the <code class="language-plaintext highlighter-rouge">random</code> library, check the <a href="https://docs.python.org/3.5/library/random.html">Python 3 documentation of the random library</a>.</p>
<p>The two methods that might be useful for this exercise are <code class="language-plaintext highlighter-rouge">random.choice()</code> or <code class="language-plaintext highlighter-rouge">random.randint()</code>. The documentation is easy to read, so check out the docs for how these methods work!</p>
https://practicepython.org/solution/2016/09/11/29-tic-tac-toe-game-solutions29 Tic Tac Toe Game Solutions2016-09-11T00:00:00+00:002016-09-11T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In 3 previous exercises, we built up a few components needed to build a Tic Tac Toe game in Python:</p>
<ol>
<li><a href="/exercise/2014/12/27/24-draw-a-game-board.html">Draw the Tic Tac Toe game board</a></li>
<li><a href="/exercise/2015/11/16/26-check-tic-tac-toe.html">Checking whether a game board has a winner</a></li>
<li><a href="/exercise/2015/11/26/27-tic-tac-toe-draw.html">Handle a player move from user input</a></li>
</ol>
<p>The next step is to put all these three components together to make a two-player Tic Tac Toe game!</p>
<h2 id="sample-solution">Sample solution</h2>
<p>This exercise is unique because it relies on the output of the other exercises that need to be put together to make the final solution. The goal is to get practice with functions and how they work together in larger programs.</p>
<p>The 3 exercises above suggest breaking your Tic Tac Toe game into (at least) 4 functions:</p>
<ol>
<li>A function for drawing the game board (and the location of pieces)</li>
<li>A function for checking whether there is a winner in the game</li>
<li>A function for adding user input into the game state</li>
<li>A main function that calls the others and plays the game</li>
</ol>
<p>The way to solve this problem is to look back at all 3 solutions to the previous exercises, copy them into one file, and modify what you had before. This is a different way of coding than coding an entire program from scratch, and can often save a lot of time.</p>
<p>For my solution, I decided to copy all the functions from the older exercises into one file, and work from the main game logic from <a href="/exercise/2015/11/26/27-tic-tac-toe-draw.html">Part 3</a>. Part 3 almost made you write the entire game - the main loop asking users for positions and input is already there, so starting from that point and modifying will let you finish this exercise in 30 minutes!</p>
<p>Here is what my code looks like after copying in my solutions to <a href="/exercise/2014/12/27/24-draw-a-game-board.html">Part 1</a>, <a href="/exercise/2015/11/16/26-check-tic-tac-toe.html">Part 2</a>, and <a href="/exercise/2015/11/26/27-tic-tac-toe-draw.html">Part 3</a> of this exercise:</p>
<script src="https://gist.github.com/mprat/8783e0b4b3eba243ca125a522f4e0ac9.js"></script>
<p>After some modifications:</p>
<ul>
<li>to the game board drawing functions</li>
<li>adding a function to check the availability of a square</li>
<li>adding a function to check whether there are any moves available</li>
<li>updating the main game loop end condition</li>
</ul>
<p>The final product is here:</p>
<script src="https://gist.github.com/mprat/921095c93cdaa4f0a8cfcc131f261f1d.js"></script>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2016/08/03/29-tic-tac-toe-game29 Tic Tac Toe Game2016-08-03T00:00:00+00:002016-08-03T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In 3 previous exercises, we built up a few components needed to build a Tic Tac Toe game in Python:</p>
<ol>
<li><a href="/exercise/2014/12/27/24-draw-a-game-board.html">Draw the Tic Tac Toe game board</a></li>
<li><a href="/exercise/2015/11/16/26-check-tic-tac-toe.html">Checking whether a game board has a winner</a></li>
<li><a href="/exercise/2015/11/26/27-tic-tac-toe-draw.html">Handle a player move from user input</a></li>
</ol>
<p>The next step is to put all these three components together to make a two-player Tic Tac Toe game! Your challenge in this exercise is to use the functions from those previous exercises all together in the same program to make a two-player game that you can play with a friend. There are a lot of choices you will have to make when completing this exercise, so you can go as far or as little as you want with it.</p>
<p>Here are a few things to keep in mind:</p>
<ul>
<li>You should keep track of who won - if there is a winner, show a congratulatory message on the screen.</li>
<li>If there are no more moves left, don’t ask for the next player’s move!</li>
</ul>
<p>As a bonus, you can ask the players if they want to play again and keep a running tally of who won more - Player 1 or Player 2.</p>
<h1 id="tips">Tips</h1>
<p><em>Starting this exercise from scratch will take you longer than 30 minutes. The best way to save time is to reuse work that has already been done!</em></p>
<p>Because you have already done the work of the previous 3 exercises, no need to re-do them all! Simply take your code from those exercises, copy it into a new file, and start again. Even if you lost your code from those exercises, go to the solutions pages, <a href="/exercise/2014/12/27/24-draw-a-game-board.html">here</a>, <a href="/exercise/2015/11/16/26-check-tic-tac-toe.html">here</a>, and <a href="/exercise/2015/11/26/27-tic-tac-toe-draw.html">here</a>, pick your favorite solutions, and start from those!</p>
<p>A large part of programming is reusing code written by someone else to accomplish a task. Sometimes it is fun to write a solution yourself, but other times you want to build on top of something else. This exercise gives you an opportunity to practice one of the arts of programming - starting from code someone else wrote and creating something on top of it.</p>
<h2 id="resources">Resources</h2>
<p>To effectively complete this exercise, you will need to make extensive use of functions to accomplish small, modular, tasks within your larger program. Here are some resources about functions in case you get stuck:</p>
<ul>
<li><a href="/exercise/2014/04/16/11-check-primality-functions.html">The PracticePython take on functions</a></li>
<li>Learn Python the Hard Way, <a href="http://learnpythonthehardway.org/book/ex19.html">exercise 19</a> and <a href="http://learnpythonthehardway.org/book/ex21.html">exercise 21</a></li>
<li>Execute some basic code on <a href="http://www.learnpython.org/en/Functions">learnpython.org</a></li>
</ul>
<p>If you are new to Python, this might be one of the longest programs you have written so far, so have fun!</p>
https://practicepython.org/solution/2016/07/16/28-max-of-three-solutions28 Max Of Three Solutions2016-07-16T00:00:00+00:002016-07-16T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Implement a function that takes as input three variables, and returns the largest of the three. Do this without using the Python <code class="language-plaintext highlighter-rouge">max()</code> function!</p>
<h2 id="sample-solutions">Sample solutions</h2>
<p>There are many ways to answer this question, ranging from simple to complex. Here are a few reader-submitted answers!</p>
<p>This first example solution uses a series of <code class="language-plaintext highlighter-rouge">if</code> statements and comparisons to find the largest of 3 elements.</p>
<script src="https://gist.github.com/zhangyu1534/74c42eee472f929034ff373ec91b9c1c.js"></script>
<p>Another solution is a little bit less verbose, taking 3 numbers as an input, making them into a list, sorting them, and then reading off the largest element.</p>
<script src="https://gist.github.com/kuko-mainroot/d9a1109ef138c93f73a01661178b820a.js"></script>
<p>This last solution uses a more compact series of <code class="language-plaintext highlighter-rouge">if</code> statement comparisons to cover all cases of 3 elements.</p>
<script src="https://gist.github.com/kanampalli/f35bc42895fad02336b780acd60044ec.js"></script>
<p>Which one is your favorite? Why?</p>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2016/03/27/28-max-of-three28 Max Of Three2016-03-27T00:00:00+00:002016-03-27T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Implement a function that takes as input three variables, and returns the largest of the three. Do this without using the Python <code class="language-plaintext highlighter-rouge">max()</code> function!</p>
<p>The goal of this exercise is to think about some internals that Python normally takes care of for us. All you need is some variables and <code class="language-plaintext highlighter-rouge">if</code> statements!</p>
https://practicepython.org/solution/2016/03/17/27-tic-tac-toe-draw-solutions27 Tic Tac Toe Draw Solutions2016-03-17T00:00:00+00:002016-03-17T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In a <a href="/exercise/2015/11/16/26-check-tic-tac-toe.html">previous exercise</a> we explored the idea of using a list of lists as a “data structure” to store information about a tic tac toe game. In a tic tac toe game, the “game server” needs to know where the <code class="language-plaintext highlighter-rouge">X</code>s and <code class="language-plaintext highlighter-rouge">O</code>s are in the board, to know whether player 1 or player 2 (or whoever is <code class="language-plaintext highlighter-rouge">X</code> and <code class="language-plaintext highlighter-rouge">O</code> won).</p>
<p>There has also been an exercise about <a href="/exercise/2014/12/27/24-draw-a-game-board.html">drawing the actual tic tac toe gameboard</a> using text characters.</p>
<p>The next logical step is to deal with handling user input. When a player (say player 1, who is <code class="language-plaintext highlighter-rouge">X</code>) wants to place an <code class="language-plaintext highlighter-rouge">X</code> on the screen, they can’t just click on a terminal. So we are going to approximate this clicking simply by asking the user for a coordinate of where they want to place their piece.</p>
<p>As a reminder, our tic tac toe game is really a list of lists. The game starts out with an empty game board like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">game</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span></code></pre></figure>
<p>The computer asks Player 1 (X) what their move is (in the format <code class="language-plaintext highlighter-rouge">row,col</code>), and say they type <code class="language-plaintext highlighter-rouge">1,3</code>. Then the game would print out</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">game</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">X</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span></code></pre></figure>
<p>And ask Player 2 for their move, printing an <code class="language-plaintext highlighter-rouge">O</code> in that place.</p>
<p>Things to note:</p>
<ul>
<li>For this exercise, assume that player 1 (the first player to move) will always be <code class="language-plaintext highlighter-rouge">X</code> and player 2 (the second player) will always be <code class="language-plaintext highlighter-rouge">O</code>.</li>
<li>Notice how in the example I gave coordinates for where I want to move starting from (1, 1) instead of (0, 0). To people who don’t program, starting to count at 0 is a strange concept, so it is better for the user experience if the row counts and column counts start at 1. This is not required, but whichever way you choose to implement this, it should be explained to the player.</li>
<li>Ask the user to enter coordinates in the form “row,col” - a number, then a comma, then a number. Then you can use your Python skills to figure out which row and column they want their piece to be in.</li>
<li>Don’t worry about checking whether someone won the game, but if a player tries to put a piece in a game position where there already is another piece, do not allow the piece to go there.</li>
</ul>
<p>Bonus:</p>
<ul>
<li>For the “standard” exercise, don’t worry about “ending” the game - no need to keep track of how many squares are full. In a bonus version, keep track of how many squares are full and automatically stop asking for moves when there are no more valid moves.</li>
</ul>
<h2 id="sample-solutions">Sample solutions</h2>
<p>Here is one solution that does not fully complete the exercise, but gives a bit of food for thought. The <code class="language-plaintext highlighter-rouge">drawboard</code> function is a general function that can be used to draw the game board with any given inputs.</p>
<script src="https://gist.github.com/Sreekaanth91/70c64445c214ca9df8ed.js"></script>
<p>Another solution uses lots of functions, and also checks whether the game has ended!</p>
<script src="https://gist.github.com/cazyw/c2f8d6b4934b2e414055.js"></script>
<p>This solution adds some bonus functions, like checking for a winner!</p>
<script src="https://gist.github.com/maze88/effa1a7ce480c0e54ccf.js"></script>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2015/11/26/27-tic-tac-toe-draw27 Tic Tac Toe Draw2015-11-26T00:00:00+00:002015-11-26T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In a <a href="/exercise/2015/11/16/26-check-tic-tac-toe.html">previous exercise</a> we explored the idea of using a list of lists as a “data structure” to store information about a tic tac toe game. In a tic tac toe game, the “game server” needs to know where the <code class="language-plaintext highlighter-rouge">X</code>s and <code class="language-plaintext highlighter-rouge">O</code>s are in the board, to know whether player 1 or player 2 (or whoever is <code class="language-plaintext highlighter-rouge">X</code> and <code class="language-plaintext highlighter-rouge">O</code> won).</p>
<p>There has also been an exercise about <a href="/exercise/2014/12/27/24-draw-a-game-board.html">drawing the actual tic tac toe gameboard</a> using text characters.</p>
<p>The next logical step is to deal with handling user input. When a player (say player 1, who is <code class="language-plaintext highlighter-rouge">X</code>) wants to place an <code class="language-plaintext highlighter-rouge">X</code> on the screen, they can’t just click on a terminal. So we are going to approximate this clicking simply by asking the user for a coordinate of where they want to place their piece.</p>
<p>As a reminder, our tic tac toe game is really a list of lists. The game starts out with an empty game board like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">game</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span></code></pre></figure>
<p>The computer asks Player 1 (X) what their move is (in the format <code class="language-plaintext highlighter-rouge">row,col</code>), and say they type <code class="language-plaintext highlighter-rouge">1,3</code>. Then the game would print out</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">game</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">X</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span></code></pre></figure>
<p>And ask Player 2 for their move, printing an <code class="language-plaintext highlighter-rouge">O</code> in that place.</p>
<p>Things to note:</p>
<ul>
<li>For this exercise, assume that player 1 (the first player to move) will always be <code class="language-plaintext highlighter-rouge">X</code> and player 2 (the second player) will always be <code class="language-plaintext highlighter-rouge">O</code>.</li>
<li>Notice how in the example I gave coordinates for where I want to move starting from (1, 1) instead of (0, 0). To people who don’t program, starting to count at 0 is a strange concept, so it is better for the user experience if the row counts and column counts start at 1. This is not required, but whichever way you choose to implement this, it should be explained to the player.</li>
<li>Ask the user to enter coordinates in the form “row,col” - a number, then a comma, then a number. Then you can use your Python skills to figure out which row and column they want their piece to be in.</li>
<li>Don’t worry about checking whether someone won the game, but if a player tries to put a piece in a game position where there already is another piece, do not allow the piece to go there.</li>
</ul>
<p>Bonus:</p>
<ul>
<li>For the “standard” exercise, don’t worry about “ending” the game - no need to keep track of how many squares are full. In a bonus version, keep track of how many squares are full and automatically stop asking for moves when there are no more valid moves.</li>
</ul>
<h2 id="concepts">Concepts</h2>
<p>One review concept that is definitely needed (in addition to the <a href="/exercise/2014/01/29/01-character-input.html">user input</a> that is the core of the exercise) is the need to “split” strings.</p>
<p>The user will input coordinates in the form “row,col”, which <code class="language-plaintext highlighter-rouge">input()</code> will then read in as a string. But we really want the numbers that come out of that string, to know which row and column to place the piece at.</p>
<p>One approach is to use the idea of <a href="/exercise/2014/03/12/06-string-lists.html">strings as lists</a> to extract the row and column numbers. This works great if your row and column numbers are always single digits - the row will always be at index 0 and the column will always be at index 2. But this breaks when the numbers are larger than one digit (I know, not going to happen in tic tac toe, but it’s easy to image extending this to other games).</p>
<p>Instead, there are two string manipulation functions that will help you:</p>
<ol>
<li><a href="https://docs.python.org/2/library/string.html#string.split"><code class="language-plaintext highlighter-rouge">.split()</code></a> - Takes a string and returns a list, using the separator as the split criteria. So if you have a string <code class="language-plaintext highlighter-rouge">name = "John Doe"</code> and do <code class="language-plaintext highlighter-rouge">name_list = name.split(" ")</code>, <code class="language-plaintext highlighter-rouge">name_list</code> will be <code class="language-plaintext highlighter-rouge">["John", "Doe"]</code>. You can use any separator / split character you want. Just remember, that each of the elements returned back will be a string as well.</li>
<li><a href="https://docs.python.org/2/library/string.html#string.strip"><code class="language-plaintext highlighter-rouge">.strip()</code></a> - Takes a string and removes the whitespace on the left and right sides of it. So you have a string <code class="language-plaintext highlighter-rouge">name = " Michele "</code>, and you do <code class="language-plaintext highlighter-rouge">name = name.strip()</code>, and now <code class="language-plaintext highlighter-rouge">name</code> will just be <code class="language-plaintext highlighter-rouge">"Michele"</code> - nice and clean.</li>
</ol>
<p>I challenge you to figure out how to use them in the exercise!</p>
https://practicepython.org/solution/2015/11/23/26-check-tic-tac-toe-solutions26 Check Tic Tac Toe Solutions2015-11-23T00:00:00+00:002015-11-23T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>As you may have guessed, we are trying to build up to a full tic-tac-toe board. However, this is significantly more than half an hour of coding, so we’re doing it in pieces.</p>
<p>Today, we will simply focus on checking whether someone has WON a game of Tic Tac Toe, not worrying about how the moves were made.</p>
<p>If a game of Tic Tac Toe is represented as a list of lists, like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">game</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span></code></pre></figure>
<p>where a <code class="language-plaintext highlighter-rouge">0</code> means an empty square, a <code class="language-plaintext highlighter-rouge">1</code> means that player 1 put their token in that space, and a <code class="language-plaintext highlighter-rouge">2</code> means that player 2 put their token in that space.</p>
<p>Your task this week: given a 3 by 3 list of lists that represents a Tic Tac Toe game board, tell me whether anyone has won, and tell me which player won, if any. A Tic Tac Toe win is 3 in a row - either in a row, a column, or a diagonal. Don’t worry about the case where TWO people have won - assume that in every board there will only be one winner.</p>
<p>Here are some more examples to work with:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">winner_is_2</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">winner_is_1</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">winner_is_also_1</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">no_winner</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]]</span>
<span class="n">also_no_winner</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span></code></pre></figure>
<h2 id="sample-solutions">Sample solutions</h2>
<p>There were many strategies for approaching this problem. The important part is to be careful about checking rows, columns, and diagonals for winners. Things like making sure that a row of <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">0</code> doesn’t win with player number 0 is important, and making sure to count the columns and rows at the edges.</p>
<p>A few submitted solutions are below - feel free to comment if you think you have a better one, and I’ll put it up here!</p>
<p>Not using too many functions, but using the <code class="language-plaintext highlighter-rouge">numpy</code> library to transpose the game board, turning column-checking into row-checking.
<script src="https://gist.github.com/anonymous/b141c876ebc330bfeb13.js"></script></p>
<p>Using <code class="language-plaintext highlighter-rouge">set()</code> to simplify the counting.
<script src="https://gist.github.com/CurveShot/e98159a400c325dc204f.js"></script></p>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2015/11/16/26-check-tic-tac-toe26 Check Tic Tac Toe2015-11-16T00:00:00+00:002015-11-16T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>As you may have guessed, we are trying to build up to a full tic-tac-toe board. However, this is significantly more than half an hour of coding, so we’re doing it in pieces.</p>
<p>Today, we will simply focus on checking whether someone has WON a game of Tic Tac Toe, not worrying about how the moves were made.</p>
<p>If a game of Tic Tac Toe is represented as a list of lists, like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">game</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span></code></pre></figure>
<p>where a <code class="language-plaintext highlighter-rouge">0</code> means an empty square, a <code class="language-plaintext highlighter-rouge">1</code> means that player 1 put their token in that space, and a <code class="language-plaintext highlighter-rouge">2</code> means that player 2 put their token in that space.</p>
<p>Your task this week: given a 3 by 3 list of lists that represents a Tic Tac Toe game board, tell me whether anyone has won, and tell me which player won, if any. A Tic Tac Toe win is 3 in a row - either in a row, a column, or a diagonal. Don’t worry about the case where TWO people have won - assume that in every board there will only be one winner.</p>
<p>Here are some more examples to work with:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">winner_is_2</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">winner_is_1</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">winner_is_also_1</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="n">no_winner</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]]</span>
<span class="n">also_no_winner</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]]</span></code></pre></figure>
<h2 id="topics">Topics</h2>
<p>This exercise is challenging, but doable with only lists (of lists)! Lists of lists are nearly the same as lists, just a bit trickier. Remember that to get the first element in a list called <code class="language-plaintext highlighter-rouge">my_list = [5, 10, 15]</code>, you index it with a variable like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_list</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="mi">5</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">my_list</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="mi">15</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">))</span>
<span class="mi">3</span></code></pre></figure>
<p>When working with lists of lists, it is the same! Say you have a list <code class="language-plaintext highlighter-rouge">matrix = [[1, 2], [3, 4]]</code>. Then, take a look at this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">matrix</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">matrix</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">first_row</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">first_row</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">matrix</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="n">matrix</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
<span class="mi">4</span></code></pre></figure>
<p>The cool part is that you can use double-indexing to read the elements from our list of lists <code class="language-plaintext highlighter-rouge">matrix</code>! By indexing <code class="language-plaintext highlighter-rouge">matrix[0][1]</code> we are saying give me the 1st element of the 0th element of <code class="language-plaintext highlighter-rouge">matrix</code>, which in this case is <code class="language-plaintext highlighter-rouge">2</code>.</p>
https://practicepython.org/solution/2015/11/08/25-guessing-game-two-solutions25 Guessing Game Two Solutions2015-11-08T00:00:00+00:002015-11-08T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In <a href="/exercise/2014/04/02/09-guessing-game-one.html">a previous exercise</a>, we’ve written a program that “knows” a number and asks a user to guess it.</p>
<p>This time, we’re going to do exactly the opposite. You, the user, will have in your head a number between 0 and 100. The program will guess a number, and you, the user, will say whether it is too high, too low, or your number.</p>
<p>At the end of this exchange, your program should print out how many guesses it took to get your number.</p>
<p>As the writer of this program, you will have to choose how your program will strategically guess. A naive strategy can be to simply start the guessing at 1, and keep going (2, 3, 4, etc.) until you hit the number. But that’s not an optimal guessing strategy. An alternate strategy might be to guess 50 (right in the middle of the range), and then increase / decrease by 1 as needed. After you’ve written the program, try to find the optimal strategy! (We’ll talk about what is the optimal one next week with the solution.)</p>
<h2 id="sample-solution">Sample solution</h2>
<p>One user implemented an interesting strategy. Based on whether the number was lower or higher than the guess, randomly pick a number in that direction. This code is easy to read, even if it does not achieve the most efficient solution (and depends a little bit on randomness).</p>
<script src="https://gist.github.com/anonymous/4da27a975ad14d590a84.js"></script>
<p>Here is one user solution, implementing binary search:</p>
<script src="https://gist.github.com/anonymous/97e6b3f876d3b257f5cc.js"></script>
<h2 id="explanation">Explanation</h2>
<h2 id="theory">Theory</h2>
<p>The problem given in this exercise is called a search problem - the objective is to find something. It is solved by an algorithm called a search algorithm - an algorithm designed to find something. Not rocket science, I know, just terminology.</p>
<p>The most optimal solution to this problem requires an algorithm called <a href="https://en.wikipedia.org/wiki/Binary_search_algorithm">binary search</a>, the most efficient search algorithm on sorted lists (for those who know about computational complexity, binary search is an <code class="language-plaintext highlighter-rouge">O(log n)</code> algorithm).</p>
<p>In a nutshell, binary search picks an element from a sorted list, then decides (based on some feedback of the target), whether to look earlier or later in the list. In the optimal form, the binary search algorithm will always look at the “center” of the list in question. The catch is that binary search relies on having the original list in question be <em>sorted</em>, or ordered either smallest to largest or largest to smallest.</p>
<h3 id="example--code">Example + Code</h3>
<p>Let’s go through an example. Say you have this list: <code class="language-plaintext highlighter-rouge">my_list = [-10, 1, 2, 6, 7, 12, 21]</code>, and we are trying to find the element <code class="language-plaintext highlighter-rouge">12</code> in the smallest number of steps. This means we want to search through the list until we find <code class="language-plaintext highlighter-rouge">8</code>, and keep track of the index we look at. The binary search algorithm will start by looking at the item in the middle (in this case <code class="language-plaintext highlighter-rouge">6</code>). We then task, is <code class="language-plaintext highlighter-rouge">6</code> less than or greater than our target (<code class="language-plaintext highlighter-rouge">12</code>)? It is less, so we need to look at the RIGHT HALF of the list. This means our new list we are looking at is <code class="language-plaintext highlighter-rouge">[7, 12, 21]</code>. We again look at the “center” element (<code class="language-plaintext highlighter-rouge">12</code>), and compare. It is <code class="language-plaintext highlighter-rouge">12</code>, our target, so we are done!</p>
<p>In code, we can accomplish this with a <code class="language-plaintext highlighter-rouge">while</code> loop. We want to keep going until either we haven’t found the element, or our guess is equal to the element. The end conditions are <code class="language-plaintext highlighter-rouge">len(my_list) == 0</code> or <code class="language-plaintext highlighter-rouge">guess == target</code>, so the <code class="language-plaintext highlighter-rouge">while</code> loop continues while those two conditions are NOT met.</p>
<p>The function will look something like this (in Python 3), assuming the list is sorted from smallest to largest:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">my_list</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">21</span><span class="p">]</span>
<span class="n">target</span> <span class="o">=</span> <span class="mi">12</span>
<span class="n">guess</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="ow">not</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">target</span><span class="p">):</span>
<span class="n">center_index</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">guess</span> <span class="o">=</span> <span class="n">my_list</span><span class="p">[</span><span class="n">center_index</span><span class="p">]</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">></span> <span class="n">target</span><span class="p">:</span>
<span class="n">my_list</span> <span class="o">=</span> <span class="n">my_list</span><span class="p">[:</span><span class="n">center_index</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">guess</span> <span class="o"><</span> <span class="n">target</span><span class="p">:</span>
<span class="n">my_list</span> <span class="o">=</span> <span class="n">my_list</span><span class="p">[</span><span class="n">center_index</span><span class="p">:]</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">target</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Found target! Guess = "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">guess</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Target not found. Last guess = "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">guess</span><span class="p">))</span></code></pre></figure>
<p>A few tricky things to note from the code:</p>
<ul>
<li>We want to always be looking at the “center” element of the list, but if the list (or sublist) has an even number of elements, it needs to be converted into an integer, so it can be used as an index into a list. In my case, I just converted the result of the length of the list divided by 2 into an int, but there are other ways.</li>
<li>The variable <code class="language-plaintext highlighter-rouge">guess</code> has to be given a value to start, but it doesn’t matter what that value is as long as it is not equal to <code class="language-plaintext highlighter-rouge">target</code>. (<em>Why? because if <code class="language-plaintext highlighter-rouge">guess</code> were to start out equal to <code class="language-plaintext highlighter-rouge">target</code>, the loop will never happen.</em>)</li>
<li>I have two conditions in my <code class="language-plaintext highlighter-rouge">if</code> statement: if the <code class="language-plaintext highlighter-rouge">guess</code> is less than the <code class="language-plaintext highlighter-rouge">target</code>, or if <code class="language-plaintext highlighter-rouge">guess</code> is greater than the <code class="language-plaintext highlighter-rouge">target</code>. In the case of the <code class="language-plaintext highlighter-rouge">guess</code> being less than the <code class="language-plaintext highlighter-rouge">target</code>, I want to look at the half of the list on the RIGHT side of the <code class="language-plaintext highlighter-rouge">guess</code>. The way I wrote it here, I am including the <code class="language-plaintext highlighter-rouge">guess</code> element in the sublist - this is not hugely important, since we will most likely remove that element later in the process anyway.</li>
<li>You can put a <code class="language-plaintext highlighter-rouge">print(my_list)</code> and/or a <code class="language-plaintext highlighter-rouge">print(guess)</code> inside the <code class="language-plaintext highlighter-rouge">while</code> loop after the <code class="language-plaintext highlighter-rouge">if</code> statement to see the progress of the code.</li>
</ul>
<h3 id="bonus-code">Bonus code</h3>
<p>Lets way we wanted to add “monitoring” to our code. How many times did the <code class="language-plaintext highlighter-rouge">while</code> loop execute? Let’s just add a counter!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">my_list</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">21</span><span class="p">]</span>
<span class="n">target</span> <span class="o">=</span> <span class="mi">12</span>
<span class="n">guess</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">numbet_of_loops</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="ow">not</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">target</span><span class="p">):</span>
<span class="n">center_index</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">my_list</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">guess</span> <span class="o">=</span> <span class="n">my_list</span><span class="p">[</span><span class="n">center_index</span><span class="p">]</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">></span> <span class="n">target</span><span class="p">:</span>
<span class="n">my_list</span> <span class="o">=</span> <span class="n">my_list</span><span class="p">[:</span><span class="n">center_index</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">guess</span> <span class="o"><</span> <span class="n">target</span><span class="p">:</span>
<span class="n">my_list</span> <span class="o">=</span> <span class="n">my_list</span><span class="p">[</span><span class="n">center_index</span><span class="p">:]</span>
<span class="n">number_of_loops</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">guess</span> <span class="o">==</span> <span class="n">target</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Found target! Guess = "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">guess</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Target not found. Last guess = "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">guess</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">"while loop executed "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">number_of_loops</span><span class="p">)</span> <span class="o">+</span> <span class="s">" times"</span><span class="p">)</span></code></pre></figure>
<p>Try changing the value of <code class="language-plaintext highlighter-rouge">target</code> and see what happens!</p>
<p>If you are feeling excited about this code and want to play more, try this bonus challenge: what happens if the list is sorted from largest to smallest? What has to change in the code?</p>
<h3 id="answering-the-original-question">Answering the original question</h3>
<p>So, to answer the original question, there are two things that need to be modified from our code snippet above:</p>
<ol>
<li>The target needs to be set. The problem specifically specifies asking the user for feedback about whether the number is too big or too small, so that needs to be incorporated into the <code class="language-plaintext highlighter-rouge">while</code> loop.</li>
<li>The list is now not a random collection of numbers - it is all the numbers in <code class="language-plaintext highlighter-rouge">range(0, 100)</code>, so you can either construct the list that way, or compute the guesses on the fly without the list (like in the sample solution above).</li>
</ol>
<p>There are many ways to solve this problem! Try a few of them and see what you like.</p>
<h2 id="further-reading">Further reading</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Binary_search_algorithm">Wikipedia article on binary search</a></li>
<li><a href="https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/implementing-binary-search-of-an-array">Khan academy lecture on binary search</a></li>
</ul>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2015/11/01/25-guessing-game-two25 Guessing Game Two2015-11-01T00:00:00+00:002015-11-01T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>In <a href="/exercise/2014/04/02/09-guessing-game-one.html">a previous exercise</a>, we’ve written a program that “knows” a number and asks a user to guess it.</p>
<p>This time, we’re going to do exactly the opposite. You, the user, will have in your head a number between 0 and 100. The program will guess a number, and you, the user, will say whether it is too high, too low, or your number.</p>
<p>At the end of this exchange, your program should print out how many guesses it took to get your number.</p>
<p>As the writer of this program, you will have to choose how your program will strategically guess. A naive strategy can be to simply start the guessing at 1, and keep going (2, 3, 4, etc.) until you hit the number. But that’s not an optimal guessing strategy. An alternate strategy might be to guess 50 (right in the middle of the range), and then increase / decrease by 1 as needed. After you’ve written the program, try to find the optimal strategy! (We’ll talk about what is the optimal one next week with the solution.)</p>
<h2 id="topics-and-links-for-more-information">Topics and links for more information</h2>
<p>This exercise doesn’t need any functions, but it does need extensive use of variables, math, and user input.</p>
<p>You can refer to <a href="/exercise/2014/01/29/01-character-input.html">this exercise on user input</a>, <a href="/exercise/2014/03/26/08-rock-paper-scissors.html">this one on rock paper scissors</a>, and many others.</p>
<p>If you want to implement the optimal solution without thinking about it first, you can read this <a href="https://en.wikipedia.org/wiki/Binary_search_algorithm">Wikipedia article on binary search</a>.</p>
https://practicepython.org/solution/2015/11/01/24-draw-a-game-board-solutions24 Draw A Game Board Solutions2015-11-01T00:00:00+00:002015-11-01T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Time for some fake graphics! Let’s say we want to draw game boards that look like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span> </code></pre></figure>
<p>This one is 3x3 (like in tic tac toe). Obviously, they come in many other sizes (8x8 for chess, 19x19 for Go, and many more).</p>
<p>Ask the user what size game board they want to draw, and draw it for them to the screen using Python’s <code class="language-plaintext highlighter-rouge">print</code> statement.</p>
<p>Remember that in Python 3, printing to the screen is accomplished by</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">print</span><span class="p">(</span><span class="s">"Thing to show on screen"</span><span class="p">)</span></code></pre></figure>
<p><em>Hint: this requires some use of functions, as were discussed <a href="/exercise/2014/04/16/11-check-primality-functions.html">previously on this blog</a> and <a href="http://www.tutorialspoint.com/python/python_functions.htm">elsewhere on the Internet, like this TutorialsPoint link</a>.</em></p>
<h2 id="sample-solution">Sample solution</h2>
<p>Let’s break this task into pieces and use Python 3.</p>
<p>First, the user needs to a numbers that represent the size of the game board (assuming the game board will be n by n). (<em>Bonus exercise: extend the following code to make the game board not square.</em>). The following snippet assumes that the person entered a number and doesn’t do any kind of error checking - for now, that’s OK.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">board_size</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"What size of game board? "</span><span class="p">))</span></code></pre></figure>
<p>Then, we need to draw each row of the game board. Each row consists of horizontal pieces (<code class="language-plaintext highlighter-rouge">---</code>) and vertical pieces (<code class="language-plaintext highlighter-rouge">|</code>). Each of these shows up in a pattern, so we can rely on for loops to help with the rendering.</p>
<p>To print a single row, we want to do something like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">print</span><span class="p">(</span><span class="s">" --- "</span> <span class="o">*</span> <span class="n">board_size</span><span class="p">)</span></code></pre></figure>
<p>To print the vertical parts of the row, we want something like this, because we don’t care about trailing whitespace, and because we want one more vertical line than the size of the board:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">print</span><span class="p">(</span><span class="s">"| "</span> <span class="o">*</span> <span class="p">(</span><span class="n">board_size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span></code></pre></figure>
<p>For a board of size <em>board_size</em> we want to print that many horizontal pieces and vertical pieces, plus an extra horizontal piece for the bottom. Let’s use functions for this entire operation, since we might want to change the style on the game boards for later use. All together, the program will look like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">print_horiz_line</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">" --- "</span> <span class="o">*</span> <span class="n">board_size</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">print_vert_line</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">"| "</span> <span class="o">*</span> <span class="p">(</span><span class="n">board_size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">board_size</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"What size of game board? "</span><span class="p">))</span>
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">board_size</span><span class="p">):</span>
<span class="n">print_horiz_line</span><span class="p">()</span>
<span class="n">print_vert_line</span><span class="p">()</span>
<span class="k">print</span> <span class="n">horiz_line</span><span class="p">()</span></code></pre></figure>
<p>This way, if we ever decide to change the design of the game board by making it bigger, it will be easy to do! All we need to do is change the <code class="language-plaintext highlighter-rouge">print_horiz_line()</code> and <code class="language-plaintext highlighter-rouge">print_vert_line()</code> functions, and we’re all set!</p>
<h2 id="a-few-user-solutions-not-using-functions">A few user solutions not using functions</h2>
<p>This one is pretty simple, and it is specific to the 3x3 board above. There is no way to change the size. Additionally, writing out the <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> lists in the print statement are tedious and can be improved with a list comprehension or for loop.</p>
<script src="https://gist.github.com/013666be7c968cb514ce.js"> </script>
<p>The author chose to use a <code class="language-plaintext highlighter-rouge">while</code> loop instead of a <code class="language-plaintext highlighter-rouge">for</code> loop to do the printing, which was an interesting choice. But it works!
<script src="https://gist.github.com/bf21e160a74e16923664.js"> </script></p>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2014/12/27/24-draw-a-game-board24 Draw A Game Board2014-12-27T00:00:00+00:002014-12-27T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Time for some fake graphics! Let’s say we want to draw game boards that look like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="o">---</span> <span class="o">---</span> <span class="o">---</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">---</span> <span class="o">---</span> <span class="o">---</span> </code></pre></figure>
<p>This one is 3x3 (like in tic tac toe). Obviously, they come in many other sizes (8x8 for chess, 19x19 for Go, and many more).</p>
<p>Ask the user what size game board they want to draw, and draw it for them to the screen using Python’s <code class="language-plaintext highlighter-rouge">print</code> statement.</p>
<p>Remember that in Python 3, printing to the screen is accomplished by</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">print</span><span class="p">(</span><span class="s">"Thing to show on screen"</span><span class="p">)</span></code></pre></figure>
<p><em>Hint: this requires some use of functions, as were discussed <a href="/exercise/2014/04/16/11-check-primality-functions.html">previously on this blog</a> and <a href="http://www.tutorialspoint.com/python/python_functions.htm">elsewhere on the Internet, like this TutorialsPoint link</a>.</em></p>
<h2 id="topics-and-links-for-more-information">Topics and links for more information</h2>
<p>The main topic of this exercise is functions. They are tricky, and deserve lots of practice and thought. Here are a few links in case you want some more reading.</p>
<ol>
<li><a href="http://www.tutorialspoint.com/python/python_functions.htm">Functions on TutorialsPoint</a></li>
<li><a href="http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/functions.html">Hands-on Python, by Loyola University</a></li>
<li><a href="http://learnpythonthehardway.org/book/ex21.html">Learn Python the Hard Way</a></li>
<li><a href="http://zetcode.com/lang/python/functions/">ZetCode</a></li>
</ol>
<p>There are hundreds more out there - read and practice away!</p>
https://practicepython.org/solution/2014/12/25/23-file-overlap-solutions23 File Overlap Solutions2014-12-25T00:00:00+00:002014-12-25T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Given two <code class="language-plaintext highlighter-rouge">.txt</code> files that have lists of numbers in them, find the numbers that are overlapping. <a href="https://www.practicepython.org/assets/primenumbers.txt">One <code class="language-plaintext highlighter-rouge">.txt</code> file</a> has a list of all prime numbers under 1000, and <a href="https://www.practicepython.org/assets/happynumbers.txt">the other <code class="language-plaintext highlighter-rouge">.txt</code> file</a> has a list of happy numbers up to 1000.</p>
<p>(If you forgot, prime numbers are numbers that can’t be divided by any other number. And yes, happy numbers are a real thing in mathematics - you can <a href="http://en.wikipedia.org/wiki/Happy_number">look it up on Wikipedia</a>. The explanation is easier with an example, which I will describe below.)</p>
<h2 id="sample-solution">Sample solution</h2>
<p>For a simple look at the solution (without using functions and using a <code class="language-plaintext highlighter-rouge">for</code> loop), look no further. Read on for a solution using functions and list comprehensions, along with a detailed explanation in Python 3.</p>
<h3 id="the-solution-without-functions-using-a-for-loop-read-on-for-the-one-with-functions-and-the-explanation">The solution without functions using a <code class="language-plaintext highlighter-rouge">for</code> loop (read on for the one with functions and the explanation)</h3>
<script src="https://gist.github.com/mprat/897b63094f3b702e4d9e.js?file=files_overlap_nofunctions.py"> </script>
<h3 id="the-solution-with-functions-using-list-comprehensions-read-on-for-the-explanation">The solution with functions using list comprehensions (read on for the explanation)</h3>
<script src="https://gist.github.com/mprat/897b63094f3b702e4d9e.js?file=files_overlap_functions.py"> </script>
<h3 id="the-explanation">The explanation</h3>
<p>The interesting thing about this problem is that it is an extension of a <a href="/exercise/2014/03/05/05-list-overlap.html">previous exercise asking to find the overlap of two lists</a>. Instead of lists that are hard-coded into the file, the program will now read lists of information from files somewhere on the computer and perform the same overlap operation.</p>
<p>The first thing to do is open the <code class="language-plaintext highlighter-rouge">.txt</code> files and save them somewhere on your computer (easiest is in the same folder as the Python file you are working in). You notice that when you look at the file, each line of the file is an integer. Next, in Python we want to open one of the files and save the contents (as integers) into a list.</p>
<p>This code snippet, as taken from the <a href="/exercise/2014/12/14/23-file-overlap.html">Exercise 23 explanation about reading from files</a>, will open the file and print out all the lines.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'primenumbers.txt'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span></code></pre></figure>
<p>We now want to just save each line as a separate integer into the list.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">primeslist</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'primenumbers.txt'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="n">primeslist</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="p">))</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span></code></pre></figure>
<p>All we did was change the <code class="language-plaintext highlighter-rouge">print</code> into an <code class="language-plaintext highlighter-rouge">append</code> to the list, and make an empty list at the beginning. Note that before I append the <code class="language-plaintext highlighter-rouge">line</code> to my list, I turn it into an <code class="language-plaintext highlighter-rouge">int</code> with the <code class="language-plaintext highlighter-rouge">int()</code> statement.</p>
<p>Now we have a choice. We can either do this twice (copy and paste the exact same code), or write a function to do this for us whenever we want.</p>
<p>Let’s make this into a function, for explanation’s sake. What we want to do here is make a function that I give the name of the file to, and it gives back to me a list of all the numbers in that file, assuming each line contains a separate integer. We need to add two lines to our code snippet from above, the <em>function header</em> and the <em>return statement</em>. The <em>function header</em> is just the name of the function with the list of variables to return, and the <em>return statement</em> is the line <code class="language-plaintext highlighter-rouge">return list_of_ints</code> at the end of the function.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">filetolistofints</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="n">list_of_ints</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="n">list_of_ints</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="p">))</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">return</span> <span class="n">list_of_ints</span></code></pre></figure>
<p>Now I can use this function to read both of my files in two simple lines:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">primeslist</span> <span class="o">=</span> <span class="n">filetolistofints</span><span class="p">(</span><span class="s">'primenumbers.txt'</span><span class="p">)</span>
<span class="n">happieslist</span> <span class="o">=</span> <span class="n">filetolistofints</span><span class="p">(</span><span class="s">'happynumbers.txt'</span><span class="p">)</span></code></pre></figure>
<p>What I have now in my variables <code class="language-plaintext highlighter-rouge">primeslist</code> and <code class="language-plaintext highlighter-rouge">happieslist</code> are lists where each element was a number on a separate line in each of the files.</p>
<p>My last step is to find the overlap between them. I can either use two <code class="language-plaintext highlighter-rouge">for</code> loops or a <em>list comprehension</em>. (If you need a refresher, <a href="/exercise/2014/02/15/03-list-less-than-ten.html">Exercise 3</a> talks about <code class="language-plaintext highlighter-rouge">for</code> loops and <a href="/exercise/2014/03/19/07-list-comprehensions.html">Exercise 7</a> talks about list comprehensions.)</p>
<p>As a list comprehension, you construct a new list that takes each element from <code class="language-plaintext highlighter-rouge">primeslist</code> and only adds it to our new list if it is inside <code class="language-plaintext highlighter-rouge">happieslist</code>.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">overlaplist</span> <span class="o">=</span> <span class="p">[</span><span class="n">elem</span> <span class="k">for</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">primeslist</span> <span class="k">if</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">happieslist</span><span class="p">]</span></code></pre></figure>
<p>This can also be done with a for loop, as below:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">overlaplist</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">primeslist</span><span class="p">:</span>
<span class="k">if</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">happieslist</span><span class="p">:</span>
<span class="n">overlaplist</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">elem</span><span class="p">)</span></code></pre></figure>
<p>And when the loop is done, <code class="language-plaintext highlighter-rouge">overlaplist</code> will contain all the elements of the overlap.</p>
<p>Now we can just print our result (using Python 3 syntax) and be done.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">print</span><span class="p">(</span><span class="n">overlaplist</span><span class="p">)</span></code></pre></figure>
<p>For a full and concise solution once again, here it is:</p>
<script src="https://gist.github.com/mprat/897b63094f3b702e4d9e.js?file=files_overlap_functions.py"> </script>
<p>Happy hacking!</p>
https://practicepython.org/exercise/2014/12/14/23-file-overlap23 File Overlap2014-12-14T00:00:00+00:002014-12-14T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Given two <code class="language-plaintext highlighter-rouge">.txt</code> files that have lists of numbers in them, find the numbers that are overlapping. <a href="https://www.practicepython.org/assets/primenumbers.txt">One <code class="language-plaintext highlighter-rouge">.txt</code> file</a> has a list of all prime numbers under 1000, and <a href="https://www.practicepython.org/assets/happynumbers.txt">the other <code class="language-plaintext highlighter-rouge">.txt</code> file</a> has a list of happy numbers up to 1000.</p>
<p>(If you forgot, prime numbers are numbers that can’t be divided by any other number. And yes, happy numbers are a real thing in mathematics - you can <a href="http://en.wikipedia.org/wiki/Happy_number">look it up on Wikipedia</a>. The explanation is easier with an example, which I will describe below.)</p>
<h2 id="discussion">Discussion</h2>
<p>You’ll need to stitch together a few ideas of things I’ve previously talked about on this blog, so if you need a refresher in any of these topics, now is your chance! Of course, there are any number of ways to do this exercise, so these are only suggestions.</p>
<p>Topics:</p>
<ol>
<li>Reading a file, in <a href="/exercise/2014/12/06/22-read-from-file.html">Exercise 21</a></li>
<li>Number types and converting to integers from strings, in <a href="/exercise/2014/01/29/01-character-input.html">Exercise 1</a></li>
<li>Lists, in <a href="/exercise/2014/02/15/03-list-less-than-ten.html">Exercise 3</a> and <a href="/exercise/2014/03/05/05-list-overlap.html">Exercise 5</a></li>
</ol>
https://practicepython.org/solution/2014/12/14/22-read-from-file-solutions22 Read From File Solutions2014-12-14T00:00:00+00:002014-12-14T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Given a <code class="language-plaintext highlighter-rouge">.txt</code> file that has a list of a bunch of names, count how many of each name there are in the file, and print out the results to the screen. I have a <code class="language-plaintext highlighter-rouge">.txt</code> file for you, if you want to <a href="https://www.practicepython.org/assets/nameslist.txt">use it</a>!</p>
<p>Extra:</p>
<ul>
<li>Instead of using the <code class="language-plaintext highlighter-rouge">.txt</code> file from above (or instead of, if you want the challenge), take <a href="https://www.practicepython.org/assets/Training_01.txt">this <code class="language-plaintext highlighter-rouge">.txt</code> file</a>, and count how many of each “category” of each image there are. This text file is actually a list of files corresponding to the <a href="http://sundatabase.mit.edu">SUN database</a> scene recognition database, and lists the file directory hierarchy for the images. Once you take a look at the first line or two of the file, it will be clear which part represents the scene category. To do this, you’re going to have to remember a bit about string parsing in Python 3. I talked a little bit about it <a href="/exercise/2014/03/12/06-string-lists.html">in this post</a>.</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>The basics of reading any file is that you need to read each line one by one, only reading the next line if the next line exists. The skeleton code for this operation is shown here:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'filename.txt'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span></code></pre></figure>
<p>Basically, after you open the file, read one line at a time. Then, check if the line exists using the statement <code class="language-plaintext highlighter-rouge">while line</code>, and if it does, get the next line. What happens when the next time <code class="language-plaintext highlighter-rouge">line = f.readline()</code> is called and there is no next line? <code class="language-plaintext highlighter-rouge">while line</code> the next time around in the loop will return <code class="language-plaintext highlighter-rouge">False</code> and the code stops.</p>
<p>Given this skeleton, the first solution counts the different names in the <code class="language-plaintext highlighter-rouge">nameslist.txt</code> file.</p>
<script src="https://gist.github.com/mprat/f2896e03c3980e0c3654.js?file=read_from_file_small_example.py"> </script>
<p>The line <code class="language-plaintext highlighter-rouge">line = line.strip()</code> takes the string read in from the line and gets rid of all whitespaces (including the <code class="language-plaintext highlighter-rouge">\n</code> character). And the basic construction and update of the dictionary is very common in many applications.</p>
<p>The second counts how many of each category of image there are in the <code class="language-plaintext highlighter-rouge">Training_01.txt</code> file from the <a href="http://sundatabase.mit.edu">SUN image database</a>.</p>
<script src="https://gist.github.com/mprat/f2896e03c3980e0c3654.js?file=read_from_file_sun.py"> </script>
https://practicepython.org/solution/2014/12/08/21-write-to-a-file-solutions21 Write To A File Solutions2014-12-08T00:00:00+00:002014-12-08T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Take the code from the <a href="/exercise/2014/06/06/17-decode-a-web-page.html">How To Decode A Website</a> exercise (if you didn’t do it or just want to play with some different code, use the code from the <a href="/solution/2014/07/10/17-decode-a-web-page-solutions.html">solution</a>), and instead of printing the results to a screen, write the results to a txt file. In your code, just make up a name for the file you are saving to.</p>
<p>Extras:</p>
<ul>
<li>Ask the user to specify the name of the output file that will be saved.</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>The sample solution takes the out-of-the-box solution for <a href="https://gist.github.com/mprat/b042a834835cfb4bbe6c">Exercise 17</a> and adds two components:</p>
<ol>
<li>Asking the user for the name of a file</li>
<li>Substitutes every <code class="language-plaintext highlighter-rouge">print</code> statement with a statement writing to a file</li>
</ol>
<p>Here is the full solution:</p>
<script src="https://gist.github.com/mprat/068d1e6d10e01baf44cd.js?file=write-to-a-file-solutions.py"> </script>
https://practicepython.org/exercise/2014/12/06/22-read-from-file22 Read From File2014-12-06T00:00:00+00:002014-12-06T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Given a <code class="language-plaintext highlighter-rouge">.txt</code> file that has a list of a bunch of names, count how many of each name there are in the file, and print out the results to the screen. I have a <code class="language-plaintext highlighter-rouge">.txt</code> file for you, if you want to <a href="https://www.practicepython.org/assets/nameslist.txt">use it</a>!</p>
<p>Extra:</p>
<ul>
<li>Instead of using the <code class="language-plaintext highlighter-rouge">.txt</code> file from above (or instead of, if you want the challenge), take <a href="https://www.practicepython.org/assets/Training_01.txt">this <code class="language-plaintext highlighter-rouge">.txt</code> file</a>, and count how many of each “category” of each image there are. This text file is actually a list of files corresponding to the <a href="http://sundatabase.mit.edu">SUN database</a> scene recognition database, and lists the file directory hierarchy for the images. Once you take a look at the first line or two of the file, it will be clear which part represents the scene category. To do this, you’re going to have to remember a bit about string parsing in Python 3. I talked a little bit about it <a href="/exercise/2014/03/12/06-string-lists.html">in this post</a>.</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Topics:</p>
<ol>
<li>Reading a file</li>
<li>Dictionaries</li>
</ol>
<h3 id="reading-a-file">Reading a File</h3>
<p>Reading a file is very analogous to writing a file, as <a href="/exercise/2014/11/30/21-write-to-a-file.html">I discussed before in Exercise 21</a>. But, the best source is always the <a href="https://docs.python.org/3.3/tutorial/inputoutput.html#reading-and-writing-files">official Python 3.3 documentation</a>.</p>
<p>Simply, reading to a file takes two steps:</p>
<ol>
<li>Opening the file for reading</li>
<li>Read!</li>
</ol>
<p>Opening a file for reading is the same as opening for writing, just using a different flag:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'file_to_read.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">open_file</span><span class="p">:</span>
<span class="n">all_text</span> <span class="o">=</span> <span class="n">open_file</span><span class="p">.</span><span class="n">read</span><span class="p">()</span></code></pre></figure>
<p>Note how the <code class="language-plaintext highlighter-rouge">'r'</code> flag stands for “read”. The code sample from above reads the entire <code class="language-plaintext highlighter-rouge">open_file</code> all at once into the <code class="language-plaintext highlighter-rouge">all_text</code> variable. But, this means that we now have a long string in <code class="language-plaintext highlighter-rouge">all_text</code> that can then be manipulated in Python using any string methods you want.</p>
<p>Another way of reading data from the file is line by line:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'file_to_read.txt'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">open_file</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">open_file</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">while</span> <span class="n">line</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">open_file</span><span class="p">.</span><span class="n">readline</span><span class="p">()</span></code></pre></figure>
<p>Instead of <code class="language-plaintext highlighter-rouge">print(line)</code>, you can imagine doing anything you want to the line of text… If you save it to a variable, you have a string that you can then use something like <code class="language-plaintext highlighter-rouge">.strip()</code> or <code class="language-plaintext highlighter-rouge">.split()</code> with.</p>
<h3 id="dictionaries">Dictionaries</h3>
<p>Dictionaries are Python’s way of associating two pieces of data together. The <a href="https://docs.python.org/3.3/tutorial/datastructures.html#dictionaries">official documentation</a> says it all.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">student_scores</span> <span class="o">=</span> <span class="p">{</span><span class="s">'Adama'</span><span class="p">:</span> <span class="mi">100</span><span class="p">,</span> <span class="s">'Starbuck'</span><span class="p">:</span> <span class="mi">75</span><span class="p">,</span> <span class="s">'Apollo'</span><span class="p">:</span> <span class="mi">80</span><span class="p">,</span> <span class="s">'Athena'</span><span class="p">:</span> <span class="mi">85</span><span class="p">,</span> <span class="s">'Agathon'</span><span class="p">:</span> <span class="mi">90</span><span class="p">}</span></code></pre></figure>
<p>The strings (or whatever happens to the left of the <code class="language-plaintext highlighter-rouge">:</code> sign), are called <code class="language-plaintext highlighter-rouge">keys</code>. When I want to access the <code class="language-plaintext highlighter-rouge">values</code> (the things to the right of the <code class="language-plaintext highlighter-rouge">:</code> sign), I need to ask the dictionary for the value associated with the key:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">adama_score</span> <span class="o">=</span> <span class="n">student_scores</span><span class="p">[</span><span class="s">'Adama'</span><span class="p">]</span></code></pre></figure>
<p>You can then modify the score and save it back to the dictionary:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">adama_score</span> <span class="o">=</span> <span class="n">student_scores</span><span class="p">[</span><span class="s">'Adama'</span><span class="p">]</span>
<span class="n">adama_score</span> <span class="o">+=</span> <span class="mi">100</span> <span class="o">%</span> <span class="n">adama_score</span> <span class="ow">is</span> <span class="n">now</span> <span class="mf">200.</span> <span class="n">This</span> <span class="n">doesn</span><span class="s">'t change the dictionary value
student_scores['</span><span class="n">Adama</span><span class="s">'] = adama_score % the score in the dictionary is now updated</span></code></pre></figure>
<p>I can’t ask the dictionary for the key associated with a value, but I can get a list of all the keys, and the same for all the values:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">all_scores</span> <span class="o">=</span> <span class="n">student_scores</span><span class="p">.</span><span class="n">keys</span><span class="p">()</span>
<span class="n">all_names</span> <span class="o">=</span> <span class="n">student_scores</span><span class="p">.</span><span class="n">values</span><span class="p">()</span></code></pre></figure>
<p>I can use the <code class="language-plaintext highlighter-rouge">in</code> keyword (just like in lists), do <code class="language-plaintext highlighter-rouge">dictionary comprehensions</code> like list comprehensions (these are cool, take a look at the <a href="https://docs.python.org/3.3/tutorial/datastructures.html#dictionaries">official bit about these</a>), and iterate over the elements in the dictionary (the syntax is just a little bit different).</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">student_scores</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">pair</span><span class="p">)</span></code></pre></figure>
<p>And this prints out pairs of keys and values that look like: <code class="language-plaintext highlighter-rouge">(Adama, 100)</code>, etc.</p>
<p>Because dictionaries are not ordered, looping through them does not guarantee the key / value pairs coming out in a particular order. So be careful.</p>
https://practicepython.org/exercise/2014/11/30/21-write-to-a-file21 Write To A File2014-11-30T00:00:00+00:002014-11-30T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Take the code from the <a href="/exercise/2014/06/06/17-decode-a-web-page.html">How To Decode A Website</a> exercise (if you didn’t do it or just want to play with some different code, use the code from the <a href="/solution/2014/07/10/17-decode-a-web-page-solutions.html">solution</a>), and instead of printing the results to a screen, write the results to a txt file. In your code, just make up a name for the file you are saving to.</p>
<p>Extras:</p>
<ul>
<li>Ask the user to specify the name of the output file that will be saved.</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Topics:</p>
<ol>
<li>Writing to a file</li>
<li>Gotchas and warnings</li>
</ol>
<h3 id="saving-to-a-file">Saving to a file</h3>
<p>Python makes it very easy to write to a file. Depending on what kind of file you want to write to and what kind of data you are writing, your options are plenty. I will show you the simplest form of writing to a file - writing plain text to a plain old text file. In other words, writing a string to a <code class="language-plaintext highlighter-rouge">.txt</code> file.</p>
<p>The code looks like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'file_to_save.txt'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">open_file</span><span class="p">:</span>
<span class="n">open_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">'A string to write'</span><span class="p">)</span></code></pre></figure>
<p>An alternate way of writing the same code is like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">open_file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'file_to_save.txt'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span>
<span class="n">open_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">'A string to write'</span><span class="p">)</span>
<span class="n">open_file</span><span class="p">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
<p>The first is considered better programming practice, but the second might explain a little bit better what is going on in the first code sample.</p>
<p>Let’s go through line by line.</p>
<p>The <code class="language-plaintext highlighter-rouge">with open('file_to_save.txt', 'w') as open_file</code> syntax is new for us - all it means is that inside the code block indented underneath, there will be a variable called <code class="language-plaintext highlighter-rouge">open_file</code> that will represent the file object. You can pick any name for this file - it is just a variable name. The <code class="language-plaintext highlighter-rouge">open()</code> function takes two arguments - the first is the name of a file as a string (if the file does not exist, Python will create it), and a second argument that represents <em>how</em> the file should be opened. There are a few ways you can open files (read all about it <a href="https://docs.python.org/3.3/tutorial/inputoutput.html#reading-and-writing-files">at the official Python documentation</a>), but in short, there are two most common ones: <code class="language-plaintext highlighter-rouge">'r'</code> and <code class="language-plaintext highlighter-rouge">'w'</code>. <code class="language-plaintext highlighter-rouge">'r'</code> stands for “read only” and <code class="language-plaintext highlighter-rouge">'w'</code> stands for “write only” (you can open for both read and write using <code class="language-plaintext highlighter-rouge">'r+'</code>). You should tell Python which way you want to open the file - you don’t want to modify a file you are only looking at, and opening a file with <code class="language-plaintext highlighter-rouge">'w'</code> when you want to only read it will overwrite the old file.</p>
<p>When you open a file, it will look for it in the same directory as the Python program. If there is no file with that name, Python will create a file in that directory with the given name. To look for files in other directories, use the <code class="language-plaintext highlighter-rouge">../</code> notation to move up and down directories as necessary.</p>
<p>As soon as the program exists the <code class="language-plaintext highlighter-rouge">with</code> code block for any reason, it will close the file. In the second code example case, I created the file object by opening the file and saving the object to my variable <code class="language-plaintext highlighter-rouge">open_file</code>. I then had to remember to close the file manually at the end of my program. This is considered worse programming practice, because in case there is an error in the program and it terminates before hitting the <code class="language-plaintext highlighter-rouge">.close()</code> statement, there will be a floating open file object somewhere in memory. You do this enough times and it becomes a problem, especially for production environments. For playing around with Python, this is not usually a problem, but why not learn how to program correctly the first time?</p>
<p>The <code class="language-plaintext highlighter-rouge">write()</code> portion is simple - call <code class="language-plaintext highlighter-rouge">.write()</code> with a string (if something is not a string, turn it into a string first), and it will write to the end of the file.</p>
<p>When the program exists the <code class="language-plaintext highlighter-rouge">with</code> statement, the file will automatically be saved. In fact, every time after a <code class="language-plaintext highlighter-rouge">.write()</code> statement, the file will be automatically saved.</p>
<h3 id="gotchas-and-warnings">Gotchas and Warnings</h3>
<p>This all seems simple enough, but there are a few caveats to the file-writing endeavor.</p>
<ol>
<li>You always want to make sure you close a file. The easiest strategy for this is explained above - use the <code class="language-plaintext highlighter-rouge">with</code> statement rather than trying to manually remember to <code class="language-plaintext highlighter-rouge">.close()</code> the file.</li>
<li>Opening a file for writing with <code class="language-plaintext highlighter-rouge">'w'</code> will overwrite any file that currently exists with that name. If you have previously written data to that file, it is now gone as soon as Python opens it.</li>
<li>You can write <em>any</em> kind of object to any kind of file in Python, as long as you specify the correct format. The simplest thing to do is to write strings to a <code class="language-plaintext highlighter-rouge">.txt</code> file. But remember - you have to convert numbers or objects into strings before you write them to a file. In a later exercise, we’ll talk about writing to other formats.</li>
</ol>
<p>The best way to remember the caveats is to explore them yourself, so have at it!</p>
https://practicepython.org/solution/2014/11/30/20-element-search-solutions20 Element Search Solutions2014-11-30T00:00:00+00:002014-11-30T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a function that takes an ordered list of numbers (a list where the elements are in order from smallest to largest) and another number. The function decides whether or not the given number is inside the list and returns (then prints) an appropriate boolean.</p>
<p>Extras:</p>
<ul>
<li>Use binary search.</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>There are two ways of solving this problem: one version using a simple for loop to search through the elements of a list, and one using the concept of binary search, looking at the elements in the most efficient way possible.</p>
<p>To use a simple for loop, a program will look like this:</p>
<script src="https://gist.github.com/mprat/074b2a4b9411a6e04c25.js?file=element-search.py"> </script>
<p>And to use binary search, one way of writing this program is like this:</p>
<script src="https://gist.github.com/mprat/074b2a4b9411a6e04c25.js?file=element-search-binary-search.py"> </script>
<p>Note that there are many ways of implementing binary search correctly. One common technique is to use what is called “recursion” or “dynamic programming”, which calls a function from inside the function. What I have shown here is an example of binary search written with just the concepts of a <code class="language-plaintext highlighter-rouge">while</code> loop and <code class="language-plaintext highlighter-rouge">if</code> statements that we have seen before in this blog.</p>
https://practicepython.org/exercise/2014/11/11/20-element-search20 Element Search2014-11-11T00:00:00+00:002014-11-11T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a function that takes an ordered list of numbers (a list where the elements are in order from smallest to largest) and another number. The function decides whether or not the given number is inside the list and returns (then prints) an appropriate boolean.</p>
<p>Extras:</p>
<ul>
<li>Use binary search.</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Topics:</p>
<ol>
<li>Booleans - True and False</li>
<li>Equality testing</li>
<li>Binary search</li>
</ol>
<h3 id="booleans">Booleans</h3>
<p>When you are writing programs, there is often a time when you need to make a decision about something based on the truthfulness of something else. Basically, you need to make a decision based on whether something is TRUE or something is FALSE.</p>
<p>An obvious example is when using conditionals:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">michele_age</span> <span class="o">=</span> <span class="mi">22</span>
<span class="n">truth_value</span> <span class="o">=</span> <span class="n">michele_age</span> <span class="o">></span> <span class="mi">17</span>
<span class="k">if</span> <span class="p">(</span><span class="n">truth_value</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Michele can see a rated R movie"</span><span class="p">)</span></code></pre></figure>
<p>(We talked about this idea of conditionals in <a href="/exercise/2014/02/05/02-odd-or-even.html">a previous post</a>.)</p>
<p>But what is happening behind the scenes is that the statement <code class="language-plaintext highlighter-rouge">michele_age > 17</code> is being evaluated into a type that is either <code class="language-plaintext highlighter-rouge">True</code> or <code class="language-plaintext highlighter-rouge">False</code>. This is then getting stored inside the variable <code class="language-plaintext highlighter-rouge">truth_value</code>, and then the decision is being made inside the conditional.</p>
<p>Here is another example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">age</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"How old are you? "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">age</span> <span class="o">>=</span> <span class="mi">17</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"can see a rated R movie"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">age</span> <span class="o"><</span> <span class="mi">17</span> <span class="ow">and</span> <span class="n">age</span> <span class="o">></span> <span class="mi">12</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"can see a rated PG-13 movie"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"can only see rated PG movies"</span><span class="p">)</span></code></pre></figure>
<p>What the <code class="language-plaintext highlighter-rouge">while True</code> statement does at the beginning of the code segment is continue asking for an age and printing a response - it never stops. (To stop it, press CTRL-C in a terminal or in the Python shell).</p>
<p>These types - <code class="language-plaintext highlighter-rouge">True</code> and <code class="language-plaintext highlighter-rouge">False</code> are called <strong>boolean</strong> types or <strong>boolean</strong> variables. They can only take on two values, either <code class="language-plaintext highlighter-rouge">True</code> or <code class="language-plaintext highlighter-rouge">False</code>.</p>
<p>For more extensive reading on Python booleans, take a look at <a href="http://www.pythonforbeginners.com/basics/boolean">these</a> <a href="http://learnpythonthehardway.org/book/ex28.html">resources</a>.</p>
<h3 id="equality-testing-on-strings">Equality testing on strings</h3>
<p>Scenarios come up where you need to test if things are equal to each other - numbers or strings or something else. We covered this idea in <a href="/exercise/2014/02/05/02-odd-or-even.html">a previous post</a>, but it is worth returning to again, this time for strings.</p>
<p>Good thing it’s easy!</p>
<p>Remember, comparing numbers for equality is done with an <code class="language-plaintext highlighter-rouge">==</code> sign, like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">age</span> <span class="o">=</span> <span class="mi">21</span>
<span class="k">if</span> <span class="n">age</span> <span class="o">==</span> <span class="mi">21</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are 21!"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">age</span> <span class="o">></span> <span class="mi">21</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You're old."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Young one!"</span><span class="p">)</span></code></pre></figure>
<p>Turns out, comparing strings is equally (hehe..) simple, using a <code class="language-plaintext highlighter-rouge">==</code> to check for equality and <code class="language-plaintext highlighter-rouge">!=</code> to check for inequality.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">password</span> <span class="o">=</span> <span class="s">"unsafepassword"</span>
<span class="k">if</span> <span class="n">password</span> <span class="o">==</span> <span class="s">"unsafepassword"</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You may enter."</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Try again!"</span><span class="p">)</span></code></pre></figure>
<p>Or, a more practical password-checking piece of code:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">real_password</span> <span class="o">=</span> <span class="s">"unsafepassword"</span>
<span class="n">user_password</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Enter the password: "</span><span class="p">)</span>
<span class="k">while</span> <span class="n">user_password</span> <span class="o">!=</span> <span class="n">real_password</span><span class="p">:</span>
<span class="n">user_password</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Enter the password: "</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You may enter!"</span><span class="p">)</span></code></pre></figure>
<h3 id="binary-search">Binary search</h3>
<p>There are a number of ways to search for elements in a list, and there is no one correct way to do so. The point of this exercise is to get you thinking about possible ways to search for elements in the list, in an entire sequence of exercises about lists, searching, and sorting. This exercise might seem silly and easy at first, but the more you dive into this topic, the more difficult it becomes.</p>
<p>The word “binary” means there are two choices (in computers, often this is 0 or 1, but it really means any choice between two things). “Search” is to look for something. So the main idea behind binary search is to look for something in a way that gives you a decision tree for where to look, containing two choices. Let me give you an example:</p>
<p>Let’s take the list <code class="language-plaintext highlighter-rouge">a = [1, 3, 5, 30, 42, 43, 500]</code>. It is an “ordered list”, or a list where the elements in the list go from smaller to larger. Let’s say we want to know whether the element <code class="language-plaintext highlighter-rouge">9</code> is in the list or not. Here is what we do:</p>
<ul>
<li>Look at the middle element in the list - it is ‘30’. * ‘9 < 30’, so let us ignore the elements to the right of ‘30’.</li>
<li>The new list we are looking at is now <code class="language-plaintext highlighter-rouge">[1, 3, 5]</code>.</li>
<li>Look at the middle element in this new list - it is <code class="language-plaintext highlighter-rouge">3</code>.</li>
<li>‘9 > 3’, so ignore the elements to the left of <code class="language-plaintext highlighter-rouge">3</code>.</li>
<li>The new list we are looking at is <code class="language-plaintext highlighter-rouge">[5]</code>.</li>
<li>The list has one element and it is not <code class="language-plaintext highlighter-rouge">9</code>.</li>
<li><code class="language-plaintext highlighter-rouge">9</code> is not in the list.</li>
</ul>
<p>What the example shows is that in an ordered list, knowing how the element you are looking for compares to another element in the list splits the list in two - one half where the element can be, and one where it definitely cannot be. In the case where our list contains millions of elements, knowing that we can cut the “search space” in half is a great increase in efficiency.</p>
<p>When you are writing the solution, first try to write it without binary search. Then when you want to try implementing binary search, write a separate function. In the solution I will give an example for how to write a binary search in Python.</p>
https://practicepython.org/solution/2014/10/01/19-decode-a-web-page-two-solutions19 Decode A Web Page Two Solutions2014-10-01T00:00:00+00:002014-10-01T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>The <a href="/exercise/2014/07/14/19-decode-a-web-page-two.html">How To Decode A Web Page Two</a> exercise was a follow-up to the extremely challenging prelude, <a href="/exercise/2014/06/06/17-decode-a-web-page.html">How To Decode A Web Page</a>. The purpose of the original (and the follow-up exercise) was to give people a chance to poke around at a close-to-real application of Python.</p>
<p>A few people submitted solutions to this exercise (one example is given at the bottom of the page), and many of them used things that I haven’t yet talked about in the exercises. I will not go into extreme detail about how to solve this problem - I will just present the important points for one way you could solve this problem. For a more detailed solution to a similar problem, I encourage you to look at the <a href="/solution/2014/07/10/17-decode-a-web-page-solutions.html">solution to the previous exercise (How To Decode A Web Page)</a>.</p>
<p>And without further ado, a plan for achieving the solution:</p>
<ol>
<li>Use the <code class="language-plaintext highlighter-rouge">requests</code> library to load the HTML of the page into Python</li>
<li>Find out which HTML tags contain the article text</li>
<li>Use <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> to process HTML and extract the text of the article</li>
<li>Print the extracted text to the screen</li>
</ol>
<p>In my opinion, the difficult part of this exercise is figuring out the elements on the page (whether that is through HTML or CSS selectors) that contain all the text of the article. It requires knowing or exploring a little bit about CSS selectors and reading documentation. Such is the way of working with web pages.</p>
<p>A few observations on that point:</p>
<ul>
<li>The entire text of the article is on this single page - no need to move to another URL. The text is placed inside “hidden containers” that are just set to invisible.</li>
<li>It seems that article text comes inside <code class="language-plaintext highlighter-rouge">p</code> elements that are inside <code class="language-plaintext highlighter-rouge">div</code> elements of class <code class="language-plaintext highlighter-rouge">body</code> that are inside <code class="language-plaintext highlighter-rouge">div</code> elements that have classes <code class="language-plaintext highlighter-rouge">parbase</code> and <code class="language-plaintext highlighter-rouge">cn_text</code>. But it also seems that there are other things like hyperlinks and article comments also fall inside this structure.</li>
<li>When you select for this in <code class="language-plaintext highlighter-rouge">BeautifulSoup</code>, the first 7 elements that come out are links and the introduction, so we just want to ignore those.</li>
</ul>
<p>Given these observations, this solution:</p>
<script src="https://gist.github.com/mprat/6ccebfa546f72488c5ec.js"></script>
<p>prints to the screen the full text of the article.</p>
<p>The CSS selectors are complex, and it takes some practice to get comfortable with them. We’ll re-visit this later (perhaps much later), but for now I encourage you to poke around the internet and look at sources of websites, playing with <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> and figuring out how CSS selectors behave.</p>
<p>Here is an example of a user-submitted solution that is not completely automated, and that does not use the exact article specified. However, it does show you that you can start solving your own problems using the techniques I am talking about on this blog.</p>
<script src="https://gist.github.com/anonymous/b5d1287a09aa6fa555a8.js"></script>
https://practicepython.org/solution/2014/07/25/13-fibonacci-solutions13 Fibonacci Solutions2014-07-25T00:00:00+00:002014-07-25T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program that asks the user how many Fibonacci numbers to generate and then generates them. Take this opportunity to think about how you can use functions. Make sure to ask the user to enter the number of numbers in the sequence to generate.(<em>Hint: The Fibonacci seqence is a sequence of numbers where the next number in the sequence is the sum of the previous two numbers in the sequence. The sequence looks like this: 1, 1, 2, 3, 5, 8, 13, …</em>)</p>
<h2 id="sample-solution">Sample solution</h2>
<p>There are so many ways that you can use functions to generate Fibonacci numbers. Here is one user-submitted solution:</p>
<script src="https://gist.github.com/anonymous/d470f920048b0d879cb5.js"></script>
<p>And another:</p>
<script src="https://gist.github.com/avillareal98/3b29bb72e35d01bd5bf4.js"></script>
<p>This solution is using what is called the “iterative” method of computing Fibonacci numbers. This means you use some kind of loop to keep adding numbers together to get the next number.</p>
<p>An alternative way of computing Fibonacci numbers is to use <em>recursion</em>, or calling the same function over and over in a special way, to compute the Fibonacci numbers. We will talk about this in a future exercise.</p>
https://practicepython.org/solution/2014/07/18/18-cows-and-bulls-solutions18 Cows And Bulls Solutions2014-07-18T00:00:00+00:002014-07-18T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Create a program that will play the “cows and bulls” game with the user. The game works like this:</p>
<p>Randomly generate a 4-digit number. Ask the user to guess a 4-digit number. For every digit that the user guessed correctly <em>in the correct place</em>, they have a “cow”. For every digit the user guessed correctly <em>in the wrong place</em> is a “bull.” Every time the user makes a guess, tell them how many “cows” and “bulls” they have. Once the user guesses the correct number, the game is over. Keep track of the number of guesses the user makes throughout teh game and tell the user at the end.</p>
<p>Say the number generated by the computer is 1038. An example interaction could look like this:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> Welcome to the Cows and Bulls Game!
Enter a number:
>>> 1234
2 cows, 0 bulls
>>> 1256
1 cow, 1 bull
...</code></pre></figure>
<p>Until the user guesses the number.</p>
<h2 id="sample-solution">Sample solution</h2>
<p>Here is one sample solution:</p>
<script src="https://gist.github.com/Toruitas/a65fbc0aa2d8f1031ba8.js"></script>
<p>And here is another:</p>
<script src="https://gist.github.com/gkdnr/0cff049a4a3096035aa0.js"></script>
https://practicepython.org/exercise/2014/07/14/19-decode-a-web-page-two19 Decode A Web Page Two2014-07-14T00:00:00+00:002014-07-14T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Using the <code class="language-plaintext highlighter-rouge">requests</code> and <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> Python libraries, print to the screen the full text of the article on this website: <a href="http://www.vanityfair.com/society/2014/06/monica-lewinsky-humiliation-culture">http://www.vanityfair.com/society/2014/06/monica-lewinsky-humiliation-culture</a>.</p>
<p>The article is long, so it is split up between 4 pages. Your task is to print out the text to the screen so that you can read the full article without having to click any buttons.</p>
<p>(<em>Hint: The post <a href="/solution/2014/07/10/17-decode-a-web-page-solutions.html">here</a> describes in detail how to use the <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> and <code class="language-plaintext highlighter-rouge">requests</code> libraries through the solution of the exercise posted <a href="/exercise/2014/06/06/17-decode-a-web-page.html">here</a>.</em>)</p>
<p>This will just print the full text of the article to the screen. It will not make it easy to read, so next exercise we will learn how to write this text to a <code class="language-plaintext highlighter-rouge">.txt</code> file.</p>
<h2 id="discussion">Discussion</h2>
<h3 id="inspecting-html-on-a-web-page">Inspecting HTML on a web page</h3>
<p>If you have forgotten how to inspect the HTML of a web page, look at the <a href="/exercise/2014/06/06/17-decode-a-web-page.html">detailed solution to the previous exercise</a> for a very detailed explanation. In brief:</p>
<ol>
<li>Open the web page in Chrome.</li>
<li>Right-click the page and click “Inspect Element”</li>
<li>Use the magnifying glass on the bottom-left of the page to click on elements of the page and look at their properties.</li>
</ol>
https://practicepython.org/solution/2014/07/10/17-decode-a-web-page-solutions17 Decode A Web Page Solutions2014-07-10T00:00:00+00:002014-07-10T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>The <a href="/exercise/2014/06/06/17-decode-a-web-page.html">How To Decode A Website</a> exercise was a challenging one, involving many complex pieces of code and two new Python modules. When appropaching problems like this one, it helps to develop a plan for the program before executing it.</p>
<p>Our plan should be as follows:</p>
<ol>
<li>Use the <code class="language-plaintext highlighter-rouge">requests</code> library to load the HTML of the page into Python</li>
<li>Set up BeautifulSoup to process the HTML</li>
<li>Find out which HTML tags contain all the titles</li>
<li>Use BeautifulSoup to extract all the titles from the HTML</li>
<li>Format them nicely</li>
</ol>
<p>We will go through each of these steps in this detailed description.</p>
<p>First, take a look at the full program without any comments:</p>
<script src="https://gist.github.com/mprat/df2969142a75b668456c.js?file=decode-web-page-no-comments.py"> </script>
<p>Let us break this down piece by piece and line by line.</p>
<p>Line 1:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="kn">import</span> <span class="nn">requests</span></code></pre></figure>
<p>First, install the <code class="language-plaintext highlighter-rouge">requests</code> library according to <a href="https://docs.python-requests.org/en/latest/">the official documentation</a> and your operating system, then import the library into the program.</p>
<p>Next,</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span></code></pre></figure>
<p>Install <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> according to the <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-beautiful-soup">installation documentation</a>. Importing the library is not like the usual way of <code class="language-plaintext highlighter-rouge">import foo</code>. Reading the <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#making-the-soup">import / useage documentation</a> is the right approach.</p>
<p>Next:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">base_url</span> <span class="o">=</span> <span class="s">'http://www.nytimes.com'</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">base_url</span><span class="p">)</span></code></pre></figure>
<p>These lines make the request to the New York Times homepage. Making a request is simple, according to the <a href="https://docs.python-requests.org/en/latest/user/quickstart/#make-a-request">documentation</a> you supply a URL and make a GET request.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">text</span><span class="p">)</span></code></pre></figure>
<p>Reading further through the documentation, we discover that <code class="language-plaintext highlighter-rouge">r</code>, contains all the information from the request sent to the New York Times homepage. What we actually want is to look at the HTML of the page and analyze it, so we find that <code class="language-plaintext highlighter-rouge">r.text</code> returns all the HTML from the returned request.</p>
<p>After this, BeautifulSoup is the tool we use to recode the HTML. In <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#making-the-soup">the same documentation</a> that describes how to import BeautifulSoup, it describes how to import the HTML to analyze it in Python using the line of code in line 6.</p>
<p>Next we need to figure out what exactly we need to look for in the HTML decoding of the New York Times webpage. I will explain how to do this in the Chrome browser - it works in other browsers but the instructions may be slightly different. Right-click on the page, and click “Inspect Element.” Like so:</p>
<figure class="twocol-figure text-center">
<img src="/assets/img/inspect_element.png" width="100%" />
<figcaption>Figure 1: How to Inspect the HTML on a Page</figcaption>
</figure>
<p>What pops up at the bottom of the page contains all the HTML that makes up the page. Let us now find the HTML that exactly describes the headlines of the main page. Pick a headline - let’s take “Germans Order Expulsion of Top U.S. Spy in Espionage Case”. Now click the magnifying glass at the bottom of the page:</p>
<figure class="twocol-figure text-center">
<img src="/assets/img/magnifying_glass.png" width="100%" />
<figcaption>Figure 2: The Magnifying Glass</figcaption>
</figure>
<p>And move the mouse to click on the title we chose. You can see that at the bottom of the page in the HTML bar, we see the line</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"> <span class="nt"><h2</span> <span class="na">class=</span><span class="s">"story-heading"</span><span class="nt">></span> .. <span class="nt"></h2></span></code></pre></figure>
<figure class="twocol-figure text-center">
<img src="/assets/img/story-heading.png" width="100%" />
<figcaption>Figure 3: Find the CSS Class</figcaption>
</figure>
<p>Our working assumptions for the moment is that all of the story titles are embedded inside some kind of HTML tag with a class called <code class="language-plaintext highlighter-rouge">story-heading</code>. Confirm with another title or two to make sure this assumption is correct, which it is.</p>
<p>Now that we know we are looking for all elements on the page with the class <code class="language-plaintext highlighter-rouge">story-heading</code>, so we need to find the <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#find-all">documentation for how to do that</a>, with <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-by-css-class">special instructors for how to do this for a class</a>. We end up with:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">class_</span><span class="o">=</span><span class="s">"story-heading"</span><span class="p">)</span></code></pre></figure>
<p>This returns a list of all tags with <code class="language-plaintext highlighter-rouge">story-heading</code> as a class. What we need to do is loop through all of them with a <code class="language-plaintext highlighter-rouge">for</code> loop and see what format the output is in.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">story_heading</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">class_</span><span class="o">=</span><span class="s">"story-heading"</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">)</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> <h2 class="story-heading">...</code></pre></figure>
<p>If you scroll through the list of outputs, they come in two varieties:</p>
<ol>
<li>Links</li>
<li>Not links</li>
</ol>
<p>When we loop through the lines with <code class="language-plaintext highlighter-rouge">story-heading</code>, we need to take this difference into account using more <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#quick-start">BeautifulSoup magic</a>:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">story_heading</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">class_</span><span class="o">=</span><span class="s">"story-heading"</span><span class="p">):</span>
<span class="k">if</span> <span class="n">story_heading</span><span class="p">.</span><span class="n">a</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">.</span><span class="n">a</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">)</span></code></pre></figure>
<p>To see this output:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> <a href="http://www.nytimes.com/2014/07/11/...</code></pre></figure>
<p>And then remove the text from the link and the title from the list of contents:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">story_heading</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">class_</span><span class="o">=</span><span class="s">"story-heading"</span><span class="p">):</span>
<span class="k">if</span> <span class="n">story_heading</span><span class="p">.</span><span class="n">a</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">.</span><span class="n">a</span><span class="p">.</span><span class="n">text</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">.</span><span class="n">contents</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> Germans Order Expulsion of Top U.S. Spy in Espionage Case
Death Toll Rises in Gaza, as Hamas Hits New Targets in Israel
...</code></pre></figure>
<p>We are almost there! The only thing missing is the formatting - if you scroll through the list of outputs, the formatting of some titles farther down the list. There are an excess of spaces, so stripping the strings and replating all instances of new lines and tabs with regular spaces should do the trick. Take a look at the <a href="https://docs.python.org/3.3/library/stdtypes.html">Python string methods documentation</a>.</p>
<p>And this is how we get lines 8 through 12:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">story_heading</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">class_</span><span class="o">=</span><span class="s">"story-heading"</span><span class="p">):</span>
<span class="k">if</span> <span class="n">story_heading</span><span class="p">.</span><span class="n">a</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">.</span><span class="n">a</span><span class="p">.</span><span class="n">text</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="s">" "</span><span class="p">).</span><span class="n">strip</span><span class="p">())</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">story_heading</span><span class="p">.</span><span class="n">contents</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">strip</span><span class="p">())</span></code></pre></figure>
<p>And we have our list of titles!</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> Germans Order Expulsion of Top U.S. Spy in Espionage Case
Death Toll Rises in Gaza, as Hamas Hits New Targets in Israel
...</code></pre></figure>
<p>Take a look the full program with all it’s comments here:
<script src="https://gist.github.com/mprat/df2969142a75b668456c.js?file=decode-web-page-comments.py"> </script></p>
<h2 id="user-submitted-solutions">User-submitted solutions</h2>
<p>Here are some user solutions!</p>
<script src="https://gist.github.com/anonymous/6470881a65877c2f3e83.js"></script>
https://practicepython.org/exercise/2014/07/05/18-cows-and-bulls18 Cows And Bulls2014-07-05T00:00:00+00:002014-07-05T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Create a program that will play the “cows and bulls” game with the user. The game works like this:</p>
<p>Randomly generate a 4-digit number. Ask the user to guess a 4-digit number. For every digit that the user guessed correctly <em>in the correct place</em>, they have a “cow”. For every digit the user guessed correctly <em>in the wrong place</em> is a “bull.” Every time the user makes a guess, tell them how many “cows” and “bulls” they have. Once the user guesses the correct number, the game is over. Keep track of the number of guesses the user makes throughout teh game and tell the user at the end.</p>
<p>Say the number generated by the computer is 1038. An example interaction could look like this:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> Welcome to the Cows and Bulls Game!
Enter a number:
>>> 1234
2 cows, 0 bulls
>>> 1256
1 cow, 1 bull
...</code></pre></figure>
<p>Until the user guesses the number.</p>
<h2 id="concepts-for-this-week">Concepts for this week:</h2>
<ol>
<li>Randomness (we’ve covered this a few times before. Mainly in <a href="/exercise/2014/04/02/09-guessing-game-one.html">a previous exercise</a>.)</li>
<li>Functions (covered in a <a href="/exercise/2014/04/16/11-check-primality-functions.html">previous exercise</a> also)</li>
<li>Main method</li>
</ol>
<h2 id="main-method">Main method</h2>
<p>Since we have covered randomness and functions, we still need to cover the idea of a “main” method. If you have programmed before, you will wonder why you haven’t needed a main method so far in your Python code.</p>
<p>First, here is how you do it:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">square</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
<span class="k">return</span> <span class="n">num</span> <span class="o">*</span> <span class="n">num</span>
<span class="k">if</span> <span class="n">__name__</span><span class="o">==</span><span class="s">"__main__"</span><span class="p">:</span>
<span class="n">user_num</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Give me a number: "</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">square</span><span class="p">(</span><span class="n">num</span><span class="p">))</span></code></pre></figure>
<p>Note that in both <code class="language-plaintext highlighter-rouge">__name__</code> and <code class="language-plaintext highlighter-rouge">__main__</code>, there are TWO underscore (<code class="language-plaintext highlighter-rouge">_</code>) characters.</p>
<p>If you run this program, it behaves as expected: asking the use for a number and printing out the square in return. However, you might be wondering - how is this different from the way we’ve been writing programs until this point?</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">square</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
<span class="k">return</span> <span class="n">num</span> <span class="o">*</span> <span class="n">num</span>
<span class="n">user_num</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Give me a number: "</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">square</span><span class="p">(</span><span class="n">num</span><span class="p">))</span></code></pre></figure>
<p>You are correct if you think the second example will have THE SAME BEHAVIOR as in the first case. At least the way we’ve been running Python files until this point. I will attempt to explain.</p>
<p>Python does not have a specified entry point like many other languages (for example, C++ always looks for a <code class="language-plaintext highlighter-rouge">void main()</code> method to run). Python files and programs are executed line by line by the Python interpreter, from however the Python file or program is run. When the definition of a function is reached by the interpreter, the function is not run, but rather loaded to be run later. (We discussed this when we talked about functions in a <a href="/exercise/2014/04/16/11-check-primality-functions.html">previous post</a>.) Whatever is written outside of a function will get executed immediately - this includes creating variables and calling the functions that were previously loaded.</p>
<p>There are (most commonly) two ways to run a Python file:</p>
<ol>
<li>“Just running it” (which you can do from the terminal, through the “Run” button in IDLE, etc.)</li>
<li>Importing the file as a module</li>
</ol>
<p>The first way is the way that you most likely have been using if you have been doing the exercises in this blog. If you have many files in a large project, this is how you run the “entry point” file in the project.</p>
<p>The second way is more subtle: it is what happens when you write an <code class="language-plaintext highlighter-rouge">import</code> statement at the top of your file. In this exercise for example, you need to <code class="language-plaintext highlighter-rouge">import random</code> into your program to use the random module. Somewhere on your computer there is a file (or a group of Python files) that make up the <code class="language-plaintext highlighter-rouge">random</code> module, and in the process of importing them, what you are actually doing is running the file(s) from that module.</p>
<p>When you have functions defined inside a file (with the <code class="language-plaintext highlighter-rouge">def</code> keyword, like the <code class="language-plaintext highlighter-rouge">def square</code> function above) and run a file, the function is not immediately run. You can think what happens is the function is stored for future use.</p>
<p>Anything else in the file - variables created, functions that are called, operations done, etc - are executed immediately when a Python file is run.</p>
<p>However, in the case where you are importing a Python file into another, you want to load all of the functions without creating variables or executing any functions. You just want to load them to use them later. How do you reconcile this problem? With the <code class="language-plaintext highlighter-rouge">if __name__=="__main__"</code> statement. Create your variables and all your functions inside this statement, and when you import your file into another, it will not mess up your program by creating variables or calling functions.</p>
<p>What the <code class="language-plaintext highlighter-rouge">if __name__=="__main__"</code> statement from above does is ensure that variables that are created, functions that are called, operations that are done, etc ONLY when you directly run the file, not when you import it into another.</p>
https://practicepython.org/exercise/2014/06/06/17-decode-a-web-page17 Decode A Web Page2014-06-06T00:00:00+00:002014-06-06T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>Note: this is a 4-chili exercise, not because it introduces a concept (although it introduces a new library), but because this exercise is more like a project. Feel free to skip this and come back when you’re more ready!</em></p>
<p>Use the <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> and <code class="language-plaintext highlighter-rouge">requests</code> Python packages to print out a list of all the article titles on the <a href="http://www.nytimes.com">New York Times homepage</a>.</p>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>Libraries</li>
<li><code class="language-plaintext highlighter-rouge">requests</code></li>
<li><code class="language-plaintext highlighter-rouge">BeautifulSoup</code></li>
</ul>
<h3 id="libraries">Libraries</h3>
<p>Many people have written libraries in Python that do not come with the standard distribution of Python (like the <code class="language-plaintext highlighter-rouge">random</code> library mentioned <a href="/exercise/2014/04/02/09-guessing-game-one.html">in a previous post</a>). These libraries can do anything from machine learning to date and time formatting to meme generation. If you have a task you need done, most likely someone has written a library for it.</p>
<p>There are three main things to keep in mind when using a library:</p>
<ol>
<li>You need to install it. Installation in GNU/Linux based systems will generally be easier than on Windows or OSX, but there will always be documentation for how to do it.</li>
<li>You need to import it. At the top of your program, make sure you write the line <code class="language-plaintext highlighter-rouge">import requests</code>, or whatever the name of your library is. Then you can use it to your heart’s content.</li>
<li>You need to read documentation. Someone else wrote it, so the rules might not be so obvious. Anyone (or any group) that writes a Python package writes documentation for it. Eventually, reading documentation will become second nature.</li>
</ol>
<h3 id="requests">Requests</h3>
<p>One of the most useful libraries written for Python recently, <a href="https://docs.python-requests.org/en/latest/">requests</a> does “HTTP for humans.” What this means in laymen’s terms is that it asks the internet things from Python. When you type “facebook.com” into the browser, you are asking the internet to show you Facebook’s homepage.</p>
<p>In the same way, a program can ask the internet something. It might not be “show me Facebook”, but you can for example ask Github for a list of all the repositories that the user “mprat” has. You can do this with an API (Application Programming Interface). This exercise doesn’t use APIs, so we’ll talk more about those in a later post.</p>
<p>Back to showing the user a webpage. When I type “facebook.com” into the browser, Facebook sends my browser a bunch of HTML (basically, code for how the website looks). The browser then takes this HTML and shows it to me in a pretty way. (Fun fact: to see the HTML of any page in a browser, right click on the page and “Inspect Element” or “View Source” depending on your browser. In Chrome, “Inspect Element” will pop up a module at the bottom of your page where you can see the HTML from the page. This trick will come in handy when you’re doing the exercise. If you need to DO anything with this HTML, better to use a program. More posts about this coming later.) If I want to “see” a webpage with a program, all I need to do is ask it for it’s HTML and read it.</p>
<p>The ‘requests’ library does half of that job: it asks (requests, if you will) a server for information. This could be just data (through an API - more later) or in the case of this exercise, HTML.</p>
<p>Look at the <a href="https://docs.python-requests.org/en/latest/">documentation</a> for all the details you need. In this particular latest version, all you need to do to ask a website for it’s HTML is:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="kn">import</span> <span class="nn">requests</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'http://github.com'</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="n">r_html</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">text</span></code></pre></figure>
<p>Now inside the variable <code class="language-plaintext highlighter-rouge">r_html</code>, you have the HTML of the page as a string. Reading (otherwise called <strong>parsing</strong>) happens with a different Python package.</p>
<h3 id="beautifulsoup">BeautifulSoup</h3>
<p>To solve our problem of parsing (reading, understanding, interpreting) the string of HTML we got from <code class="language-plaintext highlighter-rouge">requests</code>, we use the <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/"><code class="language-plaintext highlighter-rouge">BeautifulSoup</code></a> library.</p>
<p>What it does is give a <em>hierarchical</em> (a pyramid structure) to the HTML in the document. If you don’t know anything about HTML, the <a href="http://en.wikipedia.org/wiki/HTML">Wikipedia</a> article is a good summary. For the purposes of this exercise, you don’t need to know anything about HTML beyond being able to look at it quickly.</p>
<p>Because <code class="language-plaintext highlighter-rouge">BeautifulSoup</code> takes care of interpreting our HTML for us, we can ask it things like: “give me all the lines with <code class="language-plaintext highlighter-rouge"><p></code> tags” or “find me the parent element to the <code class="language-plaintext highlighter-rouge"><title></code> element”, etc.</p>
<p>Your code would look something like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span>
<span class="c1"># some requests code here for getting r_html
</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">r_html</span><span class="p">)</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'span'</span><span class="p">,</span> <span class="s">'articletitle'</span><span class="p">).</span><span class="n">string</span></code></pre></figure>
<p>And you can do many more things in <code class="language-plaintext highlighter-rouge">BeautifulSoup</code>, but I will leave you to explore those by yourself or through other later exercises.</p>
https://practicepython.org/solution/2014/06/06/16-password-generator-solutions16 Password Generator Solutions2014-06-06T00:00:00+00:002014-06-06T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a password generator in Python. Be creative with how you generate passwords - strong passwords have a mix of lowercase letters, uppercase letters, numbers, and symbols. The passwords should be random, generating a new password every time the user asks for a new password. Include your code in a main method.</p>
<p>Extra:</p>
<ul>
<li>Ask the user how strong they want their password to be. For weak passwords, pick a word or two from a list.</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>There are so many possible solutions to this exercise, really depending on how far you want to challenge yourself. The field of security, especially as it relates to computing, is an ever-growing field with countless experts, theories, principles, and more.</p>
<p>The sample solution here is one possible way to answer the question: it generates a string of random characters. It is clean, simple, and elegant.</p>
<script src="https://gist.github.com/prgrm/a85d2da1a1be791bfdd6.js"></script>
<p>And here is another, using internal Python functions:</p>
<script src="https://gist.github.com/anonymous/4a752288b785312ca840.js"></script>
https://practicepython.org/exercise/2014/05/28/16-password-generator16 Password Generator2014-05-28T00:00:00+00:002014-05-28T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p><em>Note: this is a 4-chili exercise, not because it introduces a concept, but because this exercise is more like a project. Feel free to skip this and come back when you’re more ready!</em></p>
<p>Write a password generator in Python. Be creative with how you generate passwords - strong passwords have a mix of lowercase letters, uppercase letters, numbers, and symbols. The passwords should be random, generating a new password every time the user asks for a new password. Include your run-time code in a main method.</p>
<p>Extra:</p>
<ul>
<li>Ask the user how strong they want their password to be. For weak passwords, pick a word or two from a list.</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>There are no new topics this week, but you will need to use <a href="https://docs.python.org/3.3/library/random.html">Python’s random module</a>, described in <a href="/exercise/2014/04/02/09-guessing-game-one.html">this post</a>.</p>
https://practicepython.org/solution/2014/05/28/15-reverse-word-order-solutions15 Reverse Word Order Solutions2014-05-28T00:00:00+00:002014-05-28T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program (using functions!) that asks the user for a long string containing multiple words. Print back to the user the same string, except with the words in backwards order. For example, say I type the string:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">My</span> <span class="n">name</span> <span class="ow">is</span> <span class="n">Michele</span></code></pre></figure>
<p>Then I would see the string:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">Michele</span> <span class="ow">is</span> <span class="n">name</span> <span class="n">My</span></code></pre></figure>
<p>shown back to me.</p>
<h2 id="sample-solution">Sample solution</h2>
<p>Here is the quick, one-liner solution to the problem:</p>
<script src="https://gist.github.com/anonymous/2baf03ac1147bf767455.js"></script>
<p>But most likely you didn’t come up with that solution right away. You most likely went through a number of iterations like this:</p>
<script src="https://gist.github.com/prgrm/06d70e6d0f2d03257e9c.js"></script>
<p>But you also could have taken a hybrid approach:</p>
<script src="https://gist.github.com/Shad0walker/c8cd4e52d11c8e6aa3b5.js"></script>
https://practicepython.org/exercise/2014/05/21/15-reverse-word-order15 Reverse Word Order2014-05-21T00:00:00+00:002014-05-21T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program (using functions!) that asks the user for a long string containing multiple words. Print back to the user the same string, except with the words in backwards order. For example, say I type the string:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">My</span> <span class="n">name</span> <span class="ow">is</span> <span class="n">Michele</span></code></pre></figure>
<p>Then I would see the string:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">Michele</span> <span class="ow">is</span> <span class="n">name</span> <span class="n">My</span></code></pre></figure>
<p>shown back to me.</p>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>More string things</li>
</ul>
<h2 id="more-string-things">More string things</h2>
<p>Python has a lot of interesting things you can do with strings. I will show a few here, but you can see many more methods that may or may not be useful at the <a href="https://docs.python.org/3.3/library/stdtypes.html?highlight=strings#string-methods">official Python documentation about the string format</a>.</p>
<p>Remember that <a href="/exercise/2014/03/12/06-string-lists.html">strings are lists</a>.</p>
<h3 id="splitting-strings">Splitting strings</h3>
<p>You can “split” or tear apart strings based on a given set of characters. For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">teststring</span> <span class="o">=</span> <span class="s">"this is a test"</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">teststring</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"t"</span><span class="p">)</span></code></pre></figure>
<p>And at the end, <code class="language-plaintext highlighter-rouge">result</code> will contain the list:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="p">[</span><span class="s">''</span><span class="p">,</span> <span class="s">'his is a '</span><span class="p">,</span> <span class="s">'es'</span><span class="p">,</span> <span class="s">''</span><span class="p">]</span></code></pre></figure>
<p>Instead of <code class="language-plaintext highlighter-rouge">"t"</code>, you can write any character you want. If you do not include any character, it means “split on all whitespace”:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">teststring</span> <span class="o">=</span> <span class="s">" this has a lot of spaces and tabs"</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">testring</span><span class="p">.</span><span class="n">split</span><span class="p">()</span></code></pre></figure>
<p>Then <code class="language-plaintext highlighter-rouge">result</code> contains:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="p">[</span><span class="s">'this'</span><span class="p">,</span> <span class="s">'has'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'lot'</span><span class="p">,</span> <span class="s">'of'</span><span class="p">,</span> <span class="s">'spaces'</span><span class="p">,</span> <span class="s">'and'</span><span class="p">,</span> <span class="s">'tabs'</span><span class="p">]</span></code></pre></figure>
<h3 id="joining-strings">Joining strings</h3>
<p>You can also relatively easily “join” or “smush” strings together:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">listofstrings</span> <span class="o">=</span> <span class="p">[</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">]</span>
<span class="n">result</span> <span class="o">=</span> <span class="s">"**"</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">listofstrings</span><span class="p">)</span></code></pre></figure>
<p>Then <code class="language-plaintext highlighter-rouge">result</code> will contain the string:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> a**b**c</code></pre></figure>
<p>Take a look at the official Python documentation for more information.</p>
https://practicepython.org/solution/2014/05/21/14-list-remove-duplicates-solutions14 List Remove Duplicates Solutions2014-05-21T00:00:00+00:002014-05-21T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program (function!) that takes a list and returns a new list that contains all the elements of the first list minus all the duplicates.</p>
<p>Extras:</p>
<ul>
<li>Write two different functions to do this - one using a loop and constructing a list, and another using sets.</li>
<li>Go back and do <a href="/exercise/2014/03/05/05-list-overlap.html">Exercise 5</a> using sets, and write the solution for that in a different function.</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>This solution has two different functions doing the solution in two ways - one does it with a loop, and one with sets!</p>
<script src="https://gist.github.com/prgrm/12788827aa38748214df.js"></script>
https://practicepython.org/exercise/2014/05/15/14-list-remove-duplicates14 List Remove Duplicates2014-05-15T00:00:00+00:002014-05-15T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program (function!) that takes a list and returns a new list that contains all the elements of the first list minus all the duplicates.</p>
<p>Extras:</p>
<ul>
<li>Write two different functions to do this - one using a loop and constructing a list, and another using sets.</li>
<li>Go back and do <a href="/exercise/2014/03/05/05-list-overlap.html">Exercise 5</a> using sets, and write the solution for that in a different function.</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>Sets</li>
</ul>
<h3 id="sets">Sets</h3>
<p>In mathematics, a <strong>set</strong> is a collection of elements where no element is repeated. This becomes useful because if you know your data is stored in a set, you are guaranteed to have unique elements.</p>
<h2 id="features-of-sets">Features of sets</h2>
<ul>
<li>Sets are <strong>not ordered</strong>. This means that there is no “first element” or “last element.” There are just “elements”. You cannot ask a set for it’s “next element”.</li>
<li>There are no repeat elements in sets.</li>
<li>You can convert between sets and lists very easily.</li>
</ul>
<h2 id="in-python">In Python</h2>
<p>In Python, you make and use a set with the <code class="language-plaintext highlighter-rouge">set()</code> keyword. For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">names</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="n">names</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">"Michele"</span><span class="p">)</span>
<span class="n">names</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">"Robin"</span><span class="p">)</span>
<span class="n">names</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">"Michele"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">names</span><span class="p">)</span></code></pre></figure>
<p>And the output will be;</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="nb">set</span><span class="p">([</span><span class="s">'Michele'</span><span class="p">,</span> <span class="s">'Robin'</span><span class="p">])</span></code></pre></figure>
<p>You can do to a set almost anything you can do to a list (except ask for things like “the third element”). See the <a href="https://docs.python.org/3.3/library/stdtypes.html?highlight=set#set">Python documentation about sets</a> to get a full list of things you can do to sets.</p>
<p>You can convert from a list to a set and a set to a list pretty easily:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">names</span> <span class="o">=</span> <span class="p">[</span><span class="s">"Michele"</span><span class="p">,</span> <span class="s">"Robin"</span><span class="p">,</span> <span class="s">"Sara"</span><span class="p">,</span> <span class="s">"Michele"</span><span class="p">]</span>
<span class="n">names</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">names</span><span class="p">)</span>
<span class="n">names</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">names</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">names</span><span class="p">)</span></code></pre></figure>
<p>And the result of this will be:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> ['Michele', 'Robin', 'Sara']</code></pre></figure>
https://practicepython.org/solution/2014/05/15/12-list-ends-solutions12 List Ends Solutions2014-05-15T00:00:00+00:002014-05-15T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program that takes a list of numbers (for example, <code class="language-plaintext highlighter-rouge">a = [5, 10, 15, 20, 25]</code>) and makes a new list of only the first and last elements of the given list. For practice, write this code inside a function.</p>
<h2 id="sample-solution">Sample solution</h2>
<script src="https://gist.github.com/anonymous/c3b1ff3420bc3bd68c4d.js"></script>
https://practicepython.org/exercise/2014/04/30/13-fibonacci13 Fibonacci2014-04-30T00:00:00+00:002014-04-30T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program that asks the user how many Fibonnaci numbers to generate and then generates them. Take this opportunity to think about how you can use functions. Make sure to ask the user to enter the number of numbers in the sequence to generate.(<em>Hint: The Fibonnaci seqence is a sequence of numbers where the next number in the sequence is the sum of the previous two numbers in the sequence. The sequence looks like this: 1, 1, 2, 3, 5, 8, 13, …</em>)</p>
<h2 id="discussion">Discussion</h2>
<p>Practice functions!</p>
https://practicepython.org/exercise/2014/04/25/12-list-ends12 List Ends2014-04-25T00:00:00+00:002014-04-25T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Write a program that takes a list of numbers (for example, <code class="language-plaintext highlighter-rouge">a = [5, 10, 15, 20, 25]</code>) and makes a new list of only the first and last elements of the given list. For practice, write this code inside a function.</p>
<h2 id="concepts-to-practice">Concepts to practice</h2>
<ul>
<li>Lists and properties of lists</li>
<li>List comprehensions (maybe)</li>
<li>Functions</li>
</ul>
https://practicepython.org/exercise/2014/04/16/11-check-primality-functions11 Check Primality Functions2014-04-16T00:00:00+00:002014-04-16T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Ask the user for a number and determine whether the number is prime or not. (For those who have forgotten, a prime number is a number that has no divisors.). You can (and should!) use your answer to <a href="/exercise/2014/02/26/04-divisors.html">Exercise 4</a> to help you. Take this opportunity to practice using functions, described below.</p>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>Functions</li>
<li>Reusable functions</li>
<li>Default arguments</li>
</ul>
<h3 id="functions">Functions</h3>
<p>One of the tools programming gives us is the ability to break down problems into easier (or perhaps previously solved) or reusable subproblems. It is good practice to have a function have a single purpose, and the name of that function should hint at it’s purpose in some way.</p>
<p>Most programming languages have this idea of a function, subroutine, or subprogram. In Python, a function is a programming construct that allows exactly that.</p>
<p>Let’s look at a simple example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">get_integer</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Give me a number: "</span><span class="p">))</span></code></pre></figure>
<p>In this small example, we used the same code that asks a user for input as a tabbed line underneath this <code class="language-plaintext highlighter-rouge">def</code> statement. The <code class="language-plaintext highlighter-rouge">def</code> means that everything tabbed underneath is a function. The name <code class="language-plaintext highlighter-rouge">get_integer()</code> is just a name that I (the programmer) made up. If I just include this code inside a Python file and run it, nothing will happen - all I have done so far is wrapped my code inside of a function; I never told my program to actually RUN my function.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">get_integer</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Give me a number: "</span><span class="p">))</span>
<span class="n">age</span> <span class="o">=</span> <span class="n">get_integer</span><span class="p">()</span>
<span class="n">school_year</span> <span class="o">=</span> <span class="n">get_integer</span><span class="p">()</span>
<span class="k">if</span> <span class="n">age</span> <span class="o">></span> <span class="mi">15</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are over the age of 15"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are in grade "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">school_year</span><span class="p">))</span></code></pre></figure>
<p>What I have done here is <em>called</em> the function (told it to run) by writing <code class="language-plaintext highlighter-rouge">age = get_integer()</code>. When this line of code runs, what happens is the program will <em>execute</em> (run) the function by asking me for a number, then <em>returning</em> it (giving it back to me) by saving it inside the variable <code class="language-plaintext highlighter-rouge">age</code>. Now when I want to ask the user for another number (this time representing the school year), I do the same thing with the variable <code class="language-plaintext highlighter-rouge">school_year</code>.</p>
<h3 id="reusable-functions">Reusable functions</h3>
<p>This is all well and good, but I can make my function do much more for me. Right now, my function will always ask the user for a number by printing the string <code class="language-plaintext highlighter-rouge">"Give me a number: "</code>. What if I want to print a different string every time I ask the user for a number, but otherwise use the same idea for the function? In other words, I want a variable parameter in my function that changes every time I call the function based on something I (the programmer) want to be different.</p>
<p>I can do this by <em>passing</em> (giving) my function a variable. Like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">get_integer</span><span class="p">(</span><span class="n">help_text</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="n">help_text</span><span class="p">))</span></code></pre></figure>
<p>Now what I can do when I call the function is something like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">get_integer</span><span class="p">(</span><span class="n">help_text</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="n">help_text</span><span class="p">))</span>
<span class="n">age</span> <span class="o">=</span> <span class="n">get_integer</span><span class="p">(</span><span class="s">"Tell me your age: "</span><span class="p">)</span>
<span class="n">school_year</span> <span class="o">=</span> <span class="n">get_integer</span><span class="p">(</span><span class="s">"What grade are you in? "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">age</span> <span class="o">></span> <span class="mi">15</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are over the age of 15"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are in grade "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">school_year</span><span class="p">))</span></code></pre></figure>
<p>Now it is easier for a user to use the program, because the help text is different.</p>
<p>These variables you pass to functions are called <em>variables</em>, <em>parameters</em>, or <em>arguments</em>.</p>
<h3 id="default-arguments">Default arguments</h3>
<p>In the example above, once I have added an <em>argument</em> to my function, I always have to give an argument when I call the function. I can’t forget to give the <code class="language-plaintext highlighter-rouge">get_integer()</code> function from above a string to print to the screen. In some cases, I want there to be a “default” behavior for my function that happens when I create an argument for it but don’t give it any.</p>
<p>In the example above, if I don’t give a custom string (which may be 95% of the time I use this function), I just want the <code class="language-plaintext highlighter-rouge">input()</code> line to say <code class="language-plaintext highlighter-rouge">"Give me a number: "</code> and I want to save myself the trouble of writing this every single time I call the function. So what I can do is give my function <em>default arguments</em>. Like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">get_integer</span><span class="p">(</span><span class="n">help_text</span><span class="o">=</span><span class="s">"Give me a number: "</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="n">help_text</span><span class="p">))</span></code></pre></figure>
<p>What happens now is I can use the function in two ways: by giving it an argument and by NOT giving it an argument.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">def</span> <span class="nf">get_integer</span><span class="p">(</span><span class="n">help_text</span><span class="o">=</span><span class="s">"Give me a number: "</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="n">help_text</span><span class="p">))</span>
<span class="n">age</span> <span class="o">=</span> <span class="n">get_integer</span><span class="p">(</span><span class="s">"Tell me your age: "</span><span class="p">)</span>
<span class="n">school_year</span> <span class="o">=</span> <span class="n">get_integer</span><span class="p">()</span>
<span class="k">if</span> <span class="n">age</span> <span class="o">></span> <span class="mi">15</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are over the age of 15"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You are in grade "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">school_year</span><span class="p">))</span></code></pre></figure>
<p>The first time I call the function, it will print <code class="language-plaintext highlighter-rouge">"Tell me your age: "</code>, but the second time, it will print <code class="language-plaintext highlighter-rouge">"Give me a number: "</code>, because I did not give it a string and it will execute the default behavior.</p>
<h3 id="recap">Recap</h3>
<p>What a function does is wrap a piece of code that we want to reuse, labels it, and allows us to use it again relatively easily. You can add variables to the functions to make your code even MORE reusable, and you can add default arguments to these variables.</p>
<p>Functions are a bit strange to deal with at first, but once you master them, they will be your savior in programming. Besides, the whole point of learning programming is abstraction, problem solving, breaking down problems, and that’s exactly what functions are all about.</p>
https://practicepython.org/solution/2014/04/16/11-check-primality-functions-solutions11 Check Primality Functions Solutions2014-04-16T00:00:00+00:002014-04-16T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Ask the user for a number and determine whether the number is prime or not. (For those who have forgotten, a prime number is a number that has no divisors.). You can (and should!) use your answer to <a href="/exercise/2014/02/26/04-divisors.html">Exercise 4</a> to help you.</p>
<h2 id="sample-solution">Sample solution</h2>
<p>There are many ways of solving this problem, so here are a sample solutions:</p>
<p>This one is a different breakdown of functions to solve the problem. The strings between three <code class="language-plaintext highlighter-rouge">'''</code> marks are comments in the code that describe what each function does.</p>
<script src="https://gist.github.com/JamieMacIver/11196563.js"></script>
<p>And here is a solution without using functions. It is also a correct solution that accomplishes the given task, just without the use of functions.</p>
<script src="https://gist.github.com/evamvid/4ada99be543f08280fb0.js"></script>
<p>This solution doesn’t use functions, but does use list comprehensions, which are always fun. Thanks to Carlos for this solution. The interesting thing here is the observation that when you want to check if a number is prime, all you need to do is check the numbers from 2 to the square root of the number. This is because the pair of numbers that are both the largest factors of the number are <code class="language-plaintext highlighter-rouge">square root of x</code> and <code class="language-plaintext highlighter-rouge">square root of x</code>. Otherwise, the number you are checking for can be found by finding the corresponding factor and checking it.</p>
<script src="https://gist.github.com/cescapa/c655e8e0c1558660150f.js"></script>
<p>Another solution is a clean, short solution that uses list comprehensions.</p>
<script src="https://gist.github.com/anonymous/34620e5c9feeec8824df.js"></script>
https://practicepython.org/solution/2014/04/16/10-list-overlap-comprehensions-solutions10 List Overlap Comprehensions Solutions2014-04-16T00:00:00+00:002014-04-16T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>This week’s exercise is going to be revisiting an old exercise (see <a href="/exercise/2014/03/05/05-list-overlap.html">Exercise 5</a>), except require the solution in a different way.</p>
<p>Take two lists, say for example these two:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">]</span></code></pre></figure>
<p>and write a program that returns a list that contains only the elements that are common between the lists (without duplicates). Make sure your program works on two lists of different sizes. Write this <em>using at least one list comprehension</em>. (<em>Hint: Remember <a href="/exercise/2014/03/19/07-list-comprehensions.html">list comprehensions</a> from Exercise 7</em>).</p>
<p>Extra:</p>
<ul>
<li>Randomly generate two lists to test this</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>A user-submitted solution:</p>
<script src="https://gist.github.com/anonymous/10904252.js"></script>
<p>As a few commenters / readers of this blog have pointed out (thanks mainly to Gautam and Jeff), the exercise as posed is actually impossible to write in a single line of Python. The problem is this: the proposed reader solution (and the solution that I had in mind myself) as written above does not take into account the fact that there might be duplicates in the resulting list, where I specifically asked to not include duplicates. This means that in the simple example I gave above, <code class="language-plaintext highlighter-rouge">a</code>’s first element is <code class="language-plaintext highlighter-rouge">1</code> will be added to the <code class="language-plaintext highlighter-rouge">result</code> list because it is in <code class="language-plaintext highlighter-rouge">b</code>. But then it’s next element is also <code class="language-plaintext highlighter-rouge">1</code>, and is also in <code class="language-plaintext highlighter-rouge">b</code>, so will be added to the <code class="language-plaintext highlighter-rouge">result</code> list. So the solution as given (the comprehension <code class="language-plaintext highlighter-rouge">[i for i in a if i in b]</code>) will not yield the correct result on the example solution.</p>
<p>Instead, as pointed out by Gautam and Jeff, the simplest way to achieve this solution would be to make sure that we are only looking at unique elements from <code class="language-plaintext highlighter-rouge">a</code>, the first list in the comprehension. We have not discussed doing this easily in Python on this blog using the <code class="language-plaintext highlighter-rouge">set</code> built-in function, but if you know it, the solution will look like this:</p>
<script src="https://gist.github.com/mprat/654b5f9286bcc2469077.js?file=list-overlap-comprehensions.py"> </script>
<p>But, to achieve the same results as asked in the original question while still using a list comprehension (however, definitely not using a single line of code), would be to make sure that there is no overlap in the new list after it is constructed, using the traditional <code class="language-plaintext highlighter-rouge">for</code> loop on lists:</p>
<script src="https://gist.github.com/mprat/654b5f9286bcc2469077.js?file=list-overlap-comprehensions-for.py"> </script>
<p>Or, to practice list comprehensions again, this can be done with two list comprehensions:</p>
<script src="https://gist.github.com/mprat/654b5f9286bcc2469077.js?file=list-overlap-comprehensions-2.py"> </script>
https://practicepython.org/exercise/2014/04/10/10-list-overlap-comprehensions10 List Overlap Comprehensions2014-04-10T00:00:00+00:002014-04-10T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>This week’s exercise is going to be revisiting an old exercise (see <a href="/exercise/2014/03/05/05-list-overlap.html">Exercise 5</a>), except require the solution in a different way.</p>
<p>Take two lists, say for example these two:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">]</span></code></pre></figure>
<p>and write a program that returns a list that contains only the elements that are common between the lists (without duplicates). Make sure your program works on two lists of different sizes. Write this <s>in one line of Python</s> <em>using at least one list comprehension</em>.
(<em>Hint: Remember <a href="/exercise/2014/03/19/07-list-comprehensions.html">list comprehensions</a> from Exercise 7</em>).</p>
<p><em>The original formulation of this exercise said to write the solution using one line of Python, but a few readers pointed out that this was impossible to do without using <code class="language-plaintext highlighter-rouge">set</code>s that I had not yet discussed on the blog, so you can either choose to use the original directive and read about the <a href="https://docs.python.org/3.3/library/stdtypes.html?highlight=set#set"><code class="language-plaintext highlighter-rouge">set</code> command in Python 3.3</a>, or try to implement this on your own and use at least one list comprehension in the solution.</em></p>
<p>Extra:</p>
<ul>
<li>Randomly generate two lists to test this</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>List comprehensions</li>
<li>Random numbers, continued</li>
</ul>
<h3 id="list-comprehensions">List comprehensions</h3>
<p>We already discussed list comprehensions in <a href="/exercise/2014/03/19/07-list-comprehensions.html">Exercise 7</a>, but they can be made much more complicated.</p>
<p>For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">15</span><span class="p">]</span>
<span class="n">allproducts</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span><span class="o">*</span><span class="n">b</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">x</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">y</span><span class="p">]</span></code></pre></figure>
<p>At the end of this piece of code, <code class="language-plaintext highlighter-rouge">allproducts</code> will contain the list <code class="language-plaintext highlighter-rouge">[5, 10, 15, 10, 20, 30, 15, 30, 45]</code>. So you can put multiple for loops inside the comprehension. But you can also add more complicated conditionals:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="n">y</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">15</span><span class="p">]</span>
<span class="n">customlist</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span><span class="o">*</span><span class="n">b</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">x</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">y</span> <span class="k">if</span> <span class="n">a</span><span class="o">*</span><span class="n">b</span><span class="o">%</span><span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">]</span></code></pre></figure>
<p>Now <code class="language-plaintext highlighter-rouge">customlist</code> contains <code class="language-plaintext highlighter-rouge">[5, 15, 15, 45]</code> because only the odd products are added to the list.</p>
<p>In general, the list comprehension takes the form:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="p">[</span><span class="n">EXPRESSION</span> <span class="n">FOR_LOOPS</span> <span class="n">CONDITIONALS</span><span class="p">]</span></code></pre></figure>
<p>as shown in the examples above.</p>
<h3 id="random-numbers-continued">Random numbers, continued</h3>
<p>Try to use the <a href="https://docs.python.org/3.0/library/random.html">Python random documentation</a> to figure out how to generate a random list. As a hint look below:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">sample</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">),</span> <span class="mi">5</span><span class="p">)</span></code></pre></figure>
<p>This line of code will leave <code class="language-plaintext highlighter-rouge">a</code> containing a list of 5 random numbers from 0 to 99.</p>
https://practicepython.org/solution/2014/04/10/09-guessing-game-one-solutions09 Guessing Game One Solutions2014-04-10T00:00:00+00:002014-04-10T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Generate a random number between 1 and 9 (including 1 and 9). Ask the user to guess the number, then tell them whether they guessed too low, too high, or exactly right. (<em>Hint: remember to use the user input lessons from the very <a href="/exercise/2014/01/29/01-character-input.html">first exercise</a></em>).</p>
<p>Extras:</p>
<ul>
<li>Keep the game going until the user types “exit”</li>
<li>Keep track of how many guesses the user has taken, and when the game ends, print this out.</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<p>Great example of a solution including both extras!</p>
<script src="https://gist.github.com/JamieMacIver/10153508.js"></script>
<p>And another:</p>
<script src="https://gist.github.com/avillareal98/9a2b5e5b59880d8ea6f8.js"></script>
<p>And another, with lots of helpful text!</p>
<script src="https://gist.github.com/anonymous/0502baf8a01e3aa53550.js"></script>
https://practicepython.org/exercise/2014/04/02/09-guessing-game-one09 Guessing Game One2014-04-02T00:00:00+00:002014-04-02T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Generate a random number between 1 and 9 (including 1 and 9). Ask the user to guess the number, then tell them whether they guessed too low, too high, or exactly right. (<em>Hint: remember to use the user input lessons from the very <a href="/exercise/2014/01/29/01-character-input.html">first exercise</a></em>)</p>
<p>Extras:</p>
<ul>
<li>Keep the game going until the user types “exit”</li>
<li>Keep track of how many guesses the user has taken, and when the game ends, print this out.</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>Modules</li>
<li>Random numbers</li>
<li>User input</li>
</ul>
<h3 id="random-numbers-and-modules">Random Numbers (and Modules)</h3>
<p>This is your first exposure to using Python code that somebody else wrote. In Python, these formally-distributed code packages are called <em>modules</em>. The thing we want from a module in this exercise is the ability to generate random numbers. This comes from the <em>random</em> module.</p>
<p>To use a module, at the top of your file, type</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="kn">import</span> <span class="nn">random</span></code></pre></figure>
<p>This means you are allowing your Python program to use a module called <code class="language-plaintext highlighter-rouge">random</code> in the rest of your code.</p>
<p>To use it (and generate a random integer), now type:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span></code></pre></figure>
<p>Once you run this program, the variable <code class="language-plaintext highlighter-rouge">a</code> will have a random integer that the computer made for you, between 2 and 6 (including 2 and 6). The specific documentation for this method is <a href="https://docs.python.org/3.3/library/random.html#random.randint">here</a>.</p>
<p>There are many ways you can generate random numbers - integers, decimals, and much more. The <a href="https://docs.python.org/3.3/library/random.html">Python documentation</a> has much more detailed information about what is possible from the <code class="language-plaintext highlighter-rouge">random</code> module.</p>
<h3 id="user-input">User input</h3>
<p>We covered all you need to know in the <a href="/exercise/2014/01/29/01-character-input.html">first exercise</a> of this blog!</p>
https://practicepython.org/solution/2014/04/02/08-rock-paper-scissors-solutions08 Rock Paper Scissors Solutions2014-04-02T00:00:00+00:002014-04-02T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Make a two-player Rock-Paper-Scissors game. (<em>Hint: Ask for player plays (using <code class="language-plaintext highlighter-rouge">input</code>), compare them, print out a message of congratulations to the winner, and ask if the players want to start a new game</em>)</p>
<p>Remember the rules:</p>
<ul>
<li>Rock beats scissors</li>
<li>Scissors beats paper</li>
<li>Paper beats rock</li>
</ul>
<h2 id="sample-solution">Sample solution</h2>
<script src="https://gist.github.com/redice99/21ceca1561519f5a12bc.js"></script>
<p>Another sample solution uses a clever way of checking the winner:</p>
<script src="https://gist.github.com/springtan/6f579c3160bdcac2a0df.js"></script>
https://practicepython.org/exercise/2014/03/26/08-rock-paper-scissors08 Rock Paper Scissors2014-03-26T00:00:00+00:002014-03-26T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Make a two-player Rock-Paper-Scissors game. (<em>Hint: Ask for player plays (using <code class="language-plaintext highlighter-rouge">input</code>), compare them, print out a message of congratulations to the winner, and ask if the players want to start a new game</em>)</p>
<p>Remember the rules:</p>
<ul>
<li>Rock beats scissors</li>
<li>Scissors beats paper</li>
<li>Paper beats rock</li>
</ul>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>While loops</li>
<li>Infinite loops</li>
<li>Break statements</li>
</ul>
<h3 id="while-loops">While loops</h3>
<p>We have already discussed <code class="language-plaintext highlighter-rouge">for</code> loops, or loops that look sequentially (one by one) at elements in a list. There is a second type of loop that works in a slightly different way called a <code class="language-plaintext highlighter-rouge">while</code> loop.</p>
<p>The idea is simple: while a certain condition is <code class="language-plaintext highlighter-rouge">True</code>, keep doing something. For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="mi">5</span>
<span class="k">while</span> <span class="p">(</span><span class="n">a</span> <span class="o">></span> <span class="mi">0</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">a</span> <span class="o">-=</span> <span class="mi">1</span></code></pre></figure>
<p>The output of this code segment is:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="mi">5</span>
<span class="mi">4</span>
<span class="mi">3</span>
<span class="mi">2</span>
<span class="mi">1</span></code></pre></figure>
<p>A particularly useful way to use <code class="language-plaintext highlighter-rouge">while</code> loops is checking user input for correctness. For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">quit</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Type "enter" to quit:'</span> <span class="p">)</span>
<span class="k">while</span> <span class="n">quit</span> <span class="o">!=</span> <span class="s">"enter"</span><span class="p">:</span>
<span class="n">quit</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Type "enter" to quit:'</span> <span class="p">)</span></code></pre></figure>
<p>The uses for this are infinite, and can (and should!) be combined with conditionals to yield the most efficient results.</p>
<h3 id="infinite-loops">Infinite loops</h3>
<p>An infinite loop is a loop that never stops. This means that the condition in the beginning of the while loop will always be true.</p>
<p>For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">i</span> <span class="o">=</span> <span class="mi">5</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Inside the loop"</span><span class="p">)</span></code></pre></figure>
<p>What will happen is the loop will print out the phrase “Inside the loop” forever and ever. If you are running your computer, you will have to “kill the program” to stop it. Each operating system has a different way of “killing a program” to get out of an infinite loop.</p>
<p>On Linux: in the terminal, type “CTRL-C” to kill the program that is currently running in the terminal. If you are using the IDLE Python IDE, then you must press “CTRL-D” to exit your running program. When in doubt, do a Google search before you start programming!</p>
<p>On Windows: type “CTRL-ALT-DEL” and open the task manager to kill the program.</p>
<p>On Mac: right-click on the task, and kill the program that is running forever.</p>
<p>If you find yourself in an infinite loop, your program will never end.</p>
<h3 id="break-statements">Break statements</h3>
<p>A <code class="language-plaintext highlighter-rouge">break</code> statement stops the execution of a loop before the original condition is met. While the use of a <code class="language-plaintext highlighter-rouge">break</code> statement will often start an argument about good coding practices, sometimes it is useful.</p>
<p>For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">usr_command</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Enter your command: "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">usr_command</span> <span class="o">==</span> <span class="s">"quit"</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"You typed "</span> <span class="o">+</span> <span class="n">usr_command</span><span class="p">)</span></code></pre></figure>
<p>In this case, the <code class="language-plaintext highlighter-rouge">break</code> statement is used to break off the “infinite while loop” that we have constructed with the <code class="language-plaintext highlighter-rouge">while True</code> statement.</p>
https://practicepython.org/solution/2014/03/26/07-list-comprehensions-solutions07 List Comprehensions Solutions2014-03-26T00:00:00+00:002014-03-26T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Let’s say I give you a list saved in a variable: <code class="language-plaintext highlighter-rouge">a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]</code>. Write one line of Python that takes this list <code class="language-plaintext highlighter-rouge">a</code> and makes a new list that has only the even elements of this list in it.</p>
<h2 id="sample-solutions">Sample solutions</h2>
<p>For the meat of the solution, check this out:</p>
<script src="https://gist.github.com/anonymous/9779343.js"></script>
<p>And for a “complete” solution, look at this:</p>
<script src="https://gist.github.com/jeffhunt/9659795.js"></script>
<p>For a solution that uses the <code class="language-plaintext highlighter-rouge">random</code> library to generate test lists, check this out:</p>
<script src="https://gist.github.com/JamieMacIver/9782963.js"></script>
https://practicepython.org/exercise/2014/03/19/07-list-comprehensions07 List Comprehensions2014-03-19T00:00:00+00:002014-03-19T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Let’s say I give you a list saved in a variable: <code class="language-plaintext highlighter-rouge">a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]</code>. Write one line of Python that takes this list <code class="language-plaintext highlighter-rouge">a</code> and makes a new list that has only the even elements of this list in it.</p>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>List comprehensions</li>
</ul>
<h3 id="list-comprehensions">List comprehensions</h3>
<p>The idea of a <em>list comprehension</em> is to make code more compact to accomplish tasks involving lists. Take for example this code:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">years_of_birth</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1990</span><span class="p">,</span> <span class="mi">1991</span><span class="p">,</span> <span class="mi">1990</span><span class="p">,</span> <span class="mi">1990</span><span class="p">,</span> <span class="mi">1992</span><span class="p">,</span> <span class="mi">1991</span><span class="p">]</span>
<span class="n">ages</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">year</span> <span class="ow">in</span> <span class="n">years_of_birth</span><span class="p">:</span>
<span class="n">ages</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="mi">2014</span> <span class="o">-</span> <span class="n">year</span><span class="p">)</span></code></pre></figure>
<p>And at the end, the variable <code class="language-plaintext highlighter-rouge">ages</code> has the list <code class="language-plaintext highlighter-rouge">[24, 23, 24, 24, 22, 23]</code>. What this code did was translate the years of birth into ages, and it took us a for loop and an append statement to a new list to do that.</p>
<p>Compare to this piece of code:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">years_of_birth</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1990</span><span class="p">,</span> <span class="mi">1991</span><span class="p">,</span> <span class="mi">1990</span><span class="p">,</span> <span class="mi">1990</span><span class="p">,</span> <span class="mi">1992</span><span class="p">,</span> <span class="mi">1991</span><span class="p">]</span>
<span class="n">ages</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2014</span> <span class="o">-</span> <span class="n">year</span> <span class="k">for</span> <span class="n">year</span> <span class="ow">in</span> <span class="n">years_of_birth</span><span class="p">]</span></code></pre></figure>
<p>The second line here - the line with <code class="language-plaintext highlighter-rouge">ages</code> is a <em>list comprehension.</em></p>
<p>It accomplishes the same thing as the first code sample - at the end, the <code class="language-plaintext highlighter-rouge">ages</code> variable has a list containing <code class="language-plaintext highlighter-rouge">[24, 23, 24, 24, 22, 23]</code>, the ages corresponding to all the birthdates.</p>
<p>The idea of the list comprehension is to condense the for loop and the list appending into one simple line. Notice that the for loop just shifted to the end of the list comprehension, and the part before the <code class="language-plaintext highlighter-rouge">for</code> keyword is the thing to append to the end of the new list.</p>
<p>You can also embed <code class="language-plaintext highlighter-rouge">if</code> statements into the list comprehension - check out <a href="https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions">this reference</a> to help you out. There are many examples and a better explanation than I can ever give.</p>
https://practicepython.org/solution/2014/03/19/06-string-lists-solutions06 String Lists Solutions2014-03-19T00:00:00+00:002014-03-19T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Ask the user for a string and print out whether this string is a palindrome or not. (A <strong>palindrome</strong> is a string that reads the same forwards and backwards.)</p>
<h2 id="sample-solution">Sample solution</h2>
<h3 id="a-sample-solution-using-string-reversal">A sample solution using string reversal</h3>
<script src="https://gist.github.com/anonymous/9587781.js"></script>
<h3 id="a-sample-solution-using-for-loops">A sample solution using for loops</h3>
<script src="https://gist.github.com/mprat/29985a545306f443a982.js?file=stringlists.py"> </script>
https://practicepython.org/solution/2014/03/19/05-list-overlap-solutions05 List Overlap Solutions2014-03-19T00:00:00+00:002014-03-19T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Take two lists, say for example these two:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">]</span></code></pre></figure>
<p>and write a program that returns a list that contains only the elements that are common between the lists (without duplicates). Make sure your program works on two lists of different sizes.</p>
<h2 id="sample-solution">Sample solution</h2>
<script src="https://gist.github.com/Johnson-Ben/9395388.js"></script>
https://practicepython.org/exercise/2014/03/12/06-string-lists06 String Lists2014-03-12T00:00:00+00:002014-03-12T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Ask the user for a string and print out whether this string is a palindrome or not. (A <strong>palindrome</strong> is a string that reads the same forwards and backwards.)</p>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>List indexing</li>
<li>Strings are lists</li>
</ul>
<h3 id="list-indexing">List indexing</h3>
<p>In Python (and most programming in general), you start counting lists from the number 0. The first element in a list is “number 0”, the second is “number 1”, etc.</p>
<p>As a result, when you want to get single elements out of a list, you can ask a list for that number element:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> >>> a = [5, 10, 15, 20, 25]
>>> a[3]
20
>>> a[0]
5</code></pre></figure>
<p>There is also a convenient way to get sublists between two indices:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> >>> a = [5, 10, 15, 20, 25, 30, 35, 40]
>>> a[1:4]
[10, 15, 20]
>>> a[6:]
[35, 40]
>>> a[:-1]
[5, 10, 15, 20, 25, 30, 35]</code></pre></figure>
<p>The first number is the “start index” and the last number is the “end index.”</p>
<p>You can also include a third number in the indexing, to count how often you should read from the list:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> >>> a = [5, 10, 15, 20, 25, 30, 35, 40]
>>> a[1:5:2]
[10, 20]
>>> a[3:0:-1]
[15, 10, 5]</code></pre></figure>
<p>To read the whole list, just use the variable name (in the above examples, <code class="language-plaintext highlighter-rouge">a</code>), or you can also use <code class="language-plaintext highlighter-rouge">[:]</code> at the end of the variable name (in the above examples, <code class="language-plaintext highlighter-rouge">a[:]</code>).</p>
<h3 id="strings-are-lists">Strings are lists</h3>
<p>Because strings are lists, you can do to strings everything that you do to lists. You can iterate through them:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">string</span> <span class="o">=</span> <span class="s">"example"</span>
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">string</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"one letter: "</span> <span class="o">+</span> <span class="n">c</span></code></pre></figure>
<p>Will give the result:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> one letter: e
one letter: x
one letter: a
one letter: m
one letter: p
one letter: l
one letter: e</code></pre></figure>
<p>You can take sublists:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> >>> string = "example"
>>> s = string[0:5]
>>> print s
examp</code></pre></figure>
<p>Now <code class="language-plaintext highlighter-rouge">s</code> has the string “examp” in it.</p>
<p>Moral of the story: a string is a list.</p>
https://practicepython.org/exercise/2014/03/05/05-list-overlap05 List Overlap2014-03-05T00:00:00+00:002014-03-05T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Take two lists, say for example these two:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">]</span></code></pre></figure>
<p>and write a program that returns a list that contains only the elements that are common between the lists (without duplicates). Make sure your program works on two lists of different sizes.</p>
<p>Extras:</p>
<ol>
<li>Randomly generate two lists to test this</li>
<li>Write this in one line of Python (don’t worry if you can’t figure this out at this point - we’ll get to it soon)</li>
</ol>
<h2 id="list-properties">List properties</h2>
<p>In other words, “things you can do with lists.”</p>
<p>One of the interesting things you can do with lists in Python is figure out whether something is inside the list or not. For example:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> >>> a = [5, 10, 15, 20]
>>> 10 in a
True
>>> 3 in a
False</code></pre></figure>
<p>You can of course use this in loops, conditionals, and any other programming constructs.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">list_of_students</span> <span class="o">=</span> <span class="p">[</span><span class="s">"Michele"</span><span class="p">,</span> <span class="s">"Sara"</span><span class="p">,</span> <span class="s">"Cassie"</span><span class="p">]</span>
<span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Type name to check: "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">list_of_students</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"This student is enrolled."</span><span class="p">)</span></code></pre></figure>
https://practicepython.org/solution/2014/03/05/04-divisors-solutions04 Divisors Solutions2014-03-05T00:00:00+00:002014-03-05T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Create a program that asks the user for a number and then prints out a list of all the divisors of that number. (If you don’t know what a <em>divisor</em> is, it is a number that divides evenly into another number. For example, 13 is a divisor of 26 because 26 / 13 has no remainder.)</p>
<h2 id="sample-solution">Sample solution</h2>
<script src="https://gist.github.com/jeffhunt/9269773.js"></script>
<p>There were a number of tricky things with this exercise. First, the type conversions between input strings and integers for the <code class="language-plaintext highlighter-rouge">range()</code> function need to be carefully output. Second, the arguments to <code class="language-plaintext highlighter-rouge">range()</code> had to be carefully constructed to cover all the possible numbers. Third, the condition in the <code class="language-plaintext highlighter-rouge">if</code> statement had to be correct as well.</p>
https://practicepython.org/exercise/2014/02/26/04-divisors04 Divisors2014-02-26T00:00:00+00:002014-02-26T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Create a program that asks the user for a number and then prints out a list of all the divisors of that number. (If you don’t know what a <em>divisor</em> is, it is a number that divides evenly into another number. For example, 13 is a divisor of 26 because 26 / 13 has no remainder.)</p>
<h2 id="discussion">Discussion</h2>
<p>The topics that you need for this exercise combine lists, conditionals, and user input. There is a new concept of creating lists.</p>
<p>There is an easy way to programmatically create lists of numbers in Python.</p>
<p>To create a list of numbers from 2 to 10, just use the following code:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">x</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span></code></pre></figure>
<p>Then the variable <code class="language-plaintext highlighter-rouge">x</code> will contain the list <code class="language-plaintext highlighter-rouge">[2, 3, 4, 5, 6, 7, 8, 9, 10]</code>. Note that the second number in the <code class="language-plaintext highlighter-rouge">range()</code> function is not included in the original list.</p>
<p>Now that <code class="language-plaintext highlighter-rouge">x</code> is a list of numbers, the same for loop can be used with the list:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">x</span><span class="p">:</span>
<span class="k">print</span> <span class="n">elem</span></code></pre></figure>
<p>Will yield the result:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon"> 2
3
4
5
6
7
8
9
10</code></pre></figure>
https://practicepython.org/solution/2014/02/26/03-list-less-than-ten-solutions03 List Less Than Ten Solutions2014-02-26T00:00:00+00:002014-02-26T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Take a list, say for example this one:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">]</span></code></pre></figure>
<p>and write a program that prints out all the elements of the list that are less than 5.</p>
<p>Extras:</p>
<ol>
<li>Instead of printing the elements one by one, make a new list that has all the elements less than 5 from this list in it and print out this new list.</li>
<li>Write this in one line of Python.</li>
<li>Ask the user for a number and return a list that contains only elements from the original list <code class="language-plaintext highlighter-rouge">a</code> that are smaller than that number given by the user.</li>
</ol>
<h2 id="sample-solution">Sample solution</h2>
<p>I will note that none of the solutions that were submitted were written in one line of Python. There will be more exercises later that show you how to do this!</p>
<p>Here is a sample solution that solves the exercise, including extras 1 and 2.</p>
<script src="https://gist.github.com/anonymous/d0ed6bc6196c74cfbcf6.js"></script>
<p>And here is a sample solution that solves the exercise with extra 3.</p>
<script src="https://gist.github.com/Privishell/e244707f9a2ef6bff058.js"></script>
https://practicepython.org/exercise/2014/02/15/03-list-less-than-ten03 List Less Than Ten2014-02-15T00:00:00+00:002014-02-15T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Take a list, say for example this one:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">34</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">89</span><span class="p">]</span></code></pre></figure>
<p>and write a program that prints out all the elements of the list that are less than 5.</p>
<p>Extras:</p>
<ol>
<li>Instead of printing the elements one by one, make a new list that has all the elements less than 5 from this list in it and print out this new list.</li>
<li>Write this in one line of Python.</li>
<li>Ask the user for a number and return a list that contains only elements from the original list <code class="language-plaintext highlighter-rouge">a</code> that are smaller than that number given by the user.</li>
</ol>
<h2 id="discussion">Discussion</h2>
<p>This week’s topics:</p>
<ol>
<li>Lists</li>
<li>More conditionals (if statements)</li>
</ol>
<h3 id="lists">Lists</h3>
<p>This week’s exercise hits on a topic critical for all types and styles of programming: <strong>lists</strong>. Lists are basically an ordered way of grouping things (called <strong>elements</strong>) - the cool thing about lists in Python is that you can have a list that contains objects of multiple types. Your list can mix between strings, integers, objects, other lists, what have you.</p>
<p>The way to construct an empty list is just to do</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">x</span> <span class="o">=</span> <span class="p">[]</span></code></pre></figure>
<p>And your variable <code class="language-plaintext highlighter-rouge">x</code> now holds an empty list. To add things to this list, just “append” them to the list. Like so:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">x</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">x</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span></code></pre></figure>
<p>Your list <code class="language-plaintext highlighter-rouge">x</code> now looks like <code class="language-plaintext highlighter-rouge">[3]</code>.</p>
<p>In Python, lists are also <strong>iterables</strong>, which means you can loop through them with a <strong>for loop</strong> in a convenient way. (If you come from other languages like C++ or Java you are most likely used to using a counter to loop through indices of a list - in Python you can actually loop through the elements.) I will let the code speak for itself:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">my_list</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="s">"Michele"</span><span class="p">,</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">]]</span>
<span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">my_list</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">element</span><span class="p">)</span></code></pre></figure>
<p>Will yield the result:</p>
<figure class="highlight"><pre><code class="language-pycon" data-lang="pycon">1
3
"Michele"
[5, 6, 7]</code></pre></figure>
<p>There are many other properties of lists, but for the basic exercise all you should need is this for loop property. Future weeks will address other properties of lists.</p>
<p>For more information about lists in Python, check out these resources:</p>
<ul>
<li><a href="https://docs.python.org/3.3/tutorial/datastructures.html">The official Python documentation on lists</a></li>
<li><a href="http://www.tutorialspoint.com/python/python_lists.htm">Tutorialspoint on Python lists</a></li>
<li><a href="http://effbot.org/zone/python-list.htm">Someone else’s blog post about lists</a></li>
</ul>
<h3 id="more-conditionals">More Conditionals</h3>
<p>The nice thing about conditionals is that they follow logical operations. They can also be used to test equality. Let’s do a small example. Let’s say I want to make a piece of code that converts from a numerical grade (1-100) to a letter grade (A, B, C, D, F). The code would look like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">grade</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Enter your grade: "</span><span class="p">)</span>
<span class="k">if</span> <span class="n">grade</span> <span class="o">>=</span> <span class="mi">90</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">grade</span> <span class="o">>=</span> <span class="mi">80</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"B"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">grade</span> <span class="o">>=</span> <span class="mi">70</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"C"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">grade</span> <span class="o">>=</span> <span class="mi">65</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"D"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"F"</span><span class="p">)</span></code></pre></figure>
<p>What happens if <code class="language-plaintext highlighter-rouge">grade</code> is 50? All the conditions are false, so <code class="language-plaintext highlighter-rouge">"F"</code> gets printed on the screen. But what if <code class="language-plaintext highlighter-rouge">grade</code> is 95? Then all the conditions are true and everything gets printed, right? Nope! What happens is the program goes line by line. The first condition (grade >= 90) is satisfied, so the program enters into the code inside the <code class="language-plaintext highlighter-rouge">if</code> statement, executing <code class="language-plaintext highlighter-rouge">print("A")</code>. Once code inside a conditional has been executed, the rest of the conditions are skipped and none of the other conditionals are checked.</p>
https://practicepython.org/solution/2014/02/15/02-odd-or-even-solutions02 Odd Or Even Solutions2014-02-15T00:00:00+00:002014-02-15T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Ask the user for a number. Depending on whether the number is even or odd, print out an appropriate message to the user.</p>
<p><em>Hint: how does an even / odd number react differently when divided by 2?</em></p>
<p>Extras:</p>
<ol>
<li>If the number is a multiple of 4, print out a different message.</li>
<li>Ask the user for two numbers: one number to check (call it <code class="language-plaintext highlighter-rouge">num</code>) and one number to divide by (<code class="language-plaintext highlighter-rouge">check</code>). If <code class="language-plaintext highlighter-rouge">check</code> divides evenly into <code class="language-plaintext highlighter-rouge">num</code>, tell that to the user. If not, print a different appropriate message.</li>
</ol>
<h2 id="sample-solution">Sample solution</h2>
<p>There are many ways of doing the exercise, so I am posting a few sample solutions. The very basics:</p>
<script src="https://gist.github.com/anonymous/8838738.js"></script>
<p>And something that looks slightly more complex (but is just a more complicated conditional):</p>
<script src="https://gist.github.com/eugenepark81/1fd606c626c1946ddcc8.js"></script>
https://practicepython.org/exercise/2014/02/05/02-odd-or-even02 Odd Or Even2014-02-05T00:00:00+00:002014-02-05T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>The exercise comes first (with a few extras if you want the extra challenge or want to spend more time), followed by a discussion. Enjoy!</p>
<p>Ask the user for a number. Depending on whether the number is even or odd, print out an appropriate message to the user. <em>Hint: how does an even / odd number react differently when divided by 2?</em></p>
<p>Extras:</p>
<ol>
<li>If the number is a multiple of 4, print out a different message.</li>
<li>Ask the user for two numbers: one number to check (call it <code class="language-plaintext highlighter-rouge">num</code>) and one number to divide by (<code class="language-plaintext highlighter-rouge">check</code>). If <code class="language-plaintext highlighter-rouge">check</code> divides evenly into <code class="language-plaintext highlighter-rouge">num</code>, tell that to the user. If not, print a different appropriate message.</li>
</ol>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>Modular arithmetic (the modulus operator)</li>
<li>Conditionals (if statements)</li>
<li>Checking equality</li>
</ul>
<h3 id="modular-arithmetic-the-modulus-operator">Modular arithmetic (the modulus operator)</h3>
<p>We have been doing arithmetic (addition, subtraction, multiplication, division) since elementary school, and often it is useful for us to find not the answer to a division problem but the remainder when we do a division operation. This operation is called the “modulus operation.” For example, when I divide 5 by 3, the remainder is 2, and the sentence reads like this: “5 modulo 3 is 2.”</p>
<p>In the Python shell:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="o">>>></span> <span class="mi">5</span> <span class="o">%</span> <span class="mi">3</span>
<span class="mi">2</span>
<span class="o">>>></span> <span class="mi">6</span> <span class="o">%</span> <span class="mi">3</span>
<span class="mi">0</span>
<span class="o">>>></span> <span class="mi">7</span> <span class="o">%</span> <span class="mi">3</span>
<span class="mi">1</span></code></pre></figure>
<p>The <code class="language-plaintext highlighter-rouge">%</code> sign is exactly the modulus operator.</p>
<h3 id="conditionals">Conditionals</h3>
<p>When a computer (or a program) needs to decide something, it checks whether some condition is satisfied, which is where the term <strong>conditional</strong> comes from. Conditionals are a fancy way of saying “if statements”. If Michele was born in New York, she has an American passport. That statement is a conditional (if statement) that in this case is true. In Python this works the same way:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="k">if</span> <span class="n">age</span> <span class="o">></span> <span class="mi">17</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"can see a rated R movie"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">age</span> <span class="o"><</span> <span class="mi">17</span> <span class="ow">and</span> <span class="n">age</span> <span class="o">></span> <span class="mi">12</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"can see a rated PG-13 movie"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"can only see rated PG movies"</span><span class="p">)</span></code></pre></figure>
<p>When the program gets to the <code class="language-plaintext highlighter-rouge">if</code> statement, it will check the value of the variable called <code class="language-plaintext highlighter-rouge">age</code> against all of the conditions, in order, and will print something to the screen accordingly. Note that <code class="language-plaintext highlighter-rouge">elif</code> is a portmanteau of “else” and “if”. So if the variable <code class="language-plaintext highlighter-rouge">age</code> holds the value 15, the statement <code class="language-plaintext highlighter-rouge">"can see a rated PG-13 movie"</code> will be printed to the screen.</p>
<p>Note how the statement <code class="language-plaintext highlighter-rouge">elif age < 17 and age > 12</code> has the statement <code class="language-plaintext highlighter-rouge">and</code> - you can use <code class="language-plaintext highlighter-rouge">or</code> and <code class="language-plaintext highlighter-rouge">not</code> in the same way. Understanding a bit about logic and how it works, or being able to rationally think about logic will help you get the conditions right - oh, and a lot of practice.</p>
<p>Links about conditionals:</p>
<ul>
<li><a href="https://docs.python.org/3.3/tutorial/controlflow.html">The official Python documentation</a></li>
<li><a href="http://www.pythonforbeginners.com/basics/python-if-elif-else-statement/">Python for beginners explains conditionals</a></li>
</ul>
<h3 id="checking-for-equality-and-comparators-in-general">Checking for equality (and comparators in general)</h3>
<p>A fundamental thing you want to do with your program is check whether some number is equal to another. Say the user tells you how many questions they answered incorrectly on a practice exam, and depending on the number of correctly-answered questions, you can suggest a specific course of action. For integers, strings, floats, and many other variable types, this is done with a simple syntax: <code class="language-plaintext highlighter-rouge">==</code>. To explicitly check inequality, use <code class="language-plaintext highlighter-rouge">!=</code>.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"the variable has the value 3"</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">a</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"the variable does not have the value 3"</span><span class="p">)</span></code></pre></figure>
<p>Notice how in this example, the condition is redundant. In the first condition we are checking whether the variable <code class="language-plaintext highlighter-rouge">a</code> has the value 3 and in the second, we are checking whether <code class="language-plaintext highlighter-rouge">a</code> does NOT have the value 3. However, if the first condition is not true (<code class="language-plaintext highlighter-rouge">a</code> is in fact not 3), then the second condition is by definition true. So a more efficient way to write the above conditional is like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"the variable has the value 3"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"the variable does not have the value 3"</span><span class="p">)</span></code></pre></figure>
<p>The same equality / inequality comparisons work for strings.</p>
<p>Links about equality and comparators:</p>
<ul>
<li><a href="https://docs.python.org/3.3/library/stdtypes.html?highlight=comparison#comparisons">The official Python documentation</a></li>
</ul>
https://practicepython.org/solution/2014/02/05/01-character-input-solutions01 Character Input Solutions2014-02-05T00:00:00+00:002014-02-05T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Because I cannot include every single submission I get, I will choose one or two that are example answers and include those within each post.</p>
<p>Create a program that asks the user to enter their name and their age. Print out a message addressed to them that tells them the year that they will turn 100 years old.</p>
<h2 id="solution">Solution</h2>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"What is your name: "</span><span class="p">)</span>
<span class="n">age</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"How old are you: "</span><span class="p">))</span>
<span class="n">year</span> <span class="o">=</span> <span class="mi">2014</span> <span class="o">-</span> <span class="n">age</span> <span class="o">+</span> <span class="mi">100</span>
<span class="k">print</span><span class="p">(</span><span class="n">name</span> <span class="o">+</span> <span class="s">", you will be 100 years old in the year "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">year</span><span class="p">))</span></code></pre></figure>
https://practicepython.org/exercise/2014/01/29/01-character-input01 Character Input2014-01-29T00:00:00+00:002014-01-29T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Create a program that asks the user to enter their name and their age. Print out a message addressed to them that tells them the year that they will turn 100 years old. <em>Note: for this exercise, the expectation is that you explicitly write out the year (and therefore be out of date the next year). If you want to do this in a generic way, see <a href="/exercise/2022/03/20/39-character-input-datetime.html">exercise 39</a>.</em></p>
<p>Extras:</p>
<ol>
<li>Add on to the previous program by asking the user for another number and printing out that many copies of the previous message. (<em>Hint: <a href="http://www.mathsisfun.com/operation-order-pemdas.html">order of operations</a> exists in Python</em>)</li>
<li>Print out that many copies of the previous message on separate lines. (<em>Hint: the string <code class="language-plaintext highlighter-rouge">"\n</code> is the same as pressing the ENTER button</em>)</li>
</ol>
<h2 id="discussion">Discussion</h2>
<p>Concepts for this week:</p>
<ul>
<li>Getting user input</li>
<li>Manipulating strings (a few ways). <em><a href="/exercise/2022/03/06/38-f-strings.html">Exercise 38</a> shows another way of manipulating and displaying strings</em></li>
</ul>
<h3 id="user-input-in-python">User input in Python</h3>
<p>To get user input in Python (3), the command you use is <a href="https://docs.python.org/3.3/library/functions.html?highlight=input#input"><code class="language-plaintext highlighter-rouge">input()</code></a>. Store the result in a variable, and use it to your heart’s content. Remember that the result you get from the user will be a string, even if they enter a number.</p>
<p>For example,</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Give me your name: "</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Your name is "</span> <span class="o">+</span> <span class="n">name</span><span class="p">)</span></code></pre></figure>
<p>What this will print in the terminal (or the shell, whatever you are running Python in) will be:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="n">Give</span> <span class="n">me</span> <span class="n">your</span> <span class="n">name</span><span class="p">:</span> <span class="n">Michele</span>
<span class="n">Your</span> <span class="n">name</span> <span class="ow">is</span> <span class="n">Michele</span></code></pre></figure>
<p>What happens at the end of <code class="language-plaintext highlighter-rouge">input()</code> is that it waits for the user to type something and press ENTER. Only after the user presses ENTER does the program continue.</p>
<h3 id="manipulating-strings-a-few-ways">Manipulating strings (a few ways)</h3>
<p>What you get from the <code class="language-plaintext highlighter-rouge">input()</code> function is a string. What can you do with it?</p>
<p>First: Make the string into a number. Let’s say you are 100% positive that the user entered a number. You can turn the string into an integer with the function <a href="https://docs.python.org/3.3/library/functions.html#int"><code class="language-plaintext highlighter-rouge">int()</code></a>. (In a later exercise or two or three there will be questions about what to do when the user does NOT enter a number and you try to do this; for now don’t worry about that problem). Here is what this looks like:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">age</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"Enter your age: "</span><span class="p">)</span>
<span class="n">age</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">age</span><span class="p">)</span></code></pre></figure>
<p>(or, if you want to be more compact with your code)</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">age</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">(</span><span class="s">"Enter your age: "</span><span class="p">))</span>
</code></pre></figure>
<p>In both cases, <code class="language-plaintext highlighter-rouge">age</code> will hold a variable that is an integer, and now you can do math with it.</p>
<p>(Note, you can also turn integers into strings exactly in the opposite way,
using the <a href="https://docs.python.org/3.3/library/functions.html#str"><code class="language-plaintext highlighter-rouge">str()</code></a> function)</p>
<p>Second: Do math with strings. What do I mean by that? I mean, if I want to combine (<strong>concatenate</strong> is the computer science word for this) strings, all I need to do is add them:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="k">print</span><span class="p">(</span><span class="s">"Were"</span> <span class="o">+</span> <span class="s">"wolf"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Door"</span> <span class="o">+</span> <span class="s">"man"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"4"</span> <span class="o">+</span> <span class="s">"chan"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="s">"chan"</span><span class="p">)</span></code></pre></figure>
<p>The same works for multiplication:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">print</span><span class="p">(</span><span class="mi">4</span> <span class="o">*</span> <span class="s">"test"</span><span class="p">)</span></code></pre></figure>
<p>but division and subtraction do not work like this. In terms of multiplication, the idea of multiplyling two strings together is not well-defined. What does it mean to multiply two strings in the first place? However, it makes sense in a way to specify multiplying a string by a number - just repeat that string that number of times. Try this in your own program with all the arithmetic operations with numbers and strings - the best way to get a feel for what works and what doesn’t is to try it!</p>
https://practicepython.org/why-practice-pythonWhy Programming? Why Python? Why Now?2013-12-30T00:00:00+00:002013-12-30T00:00:00+00:00Michele Pratusevichhttps://practicepython.org<p>Programming is the missing link in education. It lets you explore, play, work with others, and fail in a safe environment. Everyone should learn to program.</p>
<!-- more -->
<h2 id="programming-is-the-missing-link-in-education">Programming is the Missing Link in Education</h2>
<p>The goal of a modern education is to nurture a person to adulthood, someone who is capable of solving the tough problems of tomorrow. However, in schools we are taught to memorize and regurgitate. Most students don’t come close to an exploratory, iterative, problem solving education. I want to tell you why programming is the best way to fill those gaps. No matter how old you are, programming practice is for you.</p>
<p>There are four <a href="http://ecologyofeducation.net/wsite/?p=2457">fundamental aspects of learning</a> that are most effective:</p>
<ol>
<li>Problem-driven and individualized</li>
<li>Fun</li>
<li>Safe from failure</li>
<li>Group engagement</li>
</ol>
<p>(there are many more, but you can read any blog, article, book about educational philosophy and fill in the gaps yourself).</p>
<p>The idea is this: if you have a problem or a goal to reach, you are free to explore options and work with trial and error at your own pace. In an environment where failure is not only OK but expected and surrounded by others facing similar problems, you will not only be empowered to solve your small problem but also build enough confidence to solve larger problems. Sound a bit idealistic? Maybe so, but it’s a good practice arena for building up the intangible skills like confidence and problem solving. When faced with a real problem (that most likely has nothing to do with programming), you will have enough on your plate trying to figure out the right answer that you want your confidence and persistence backing you up.</p>
<p>Programming is the perfect sandbox. Remember back to your 5-year-old days playing in the sandbox. You were taken to another world, filled with ants and dunes and trucks and shovels. Nothing played by the rules of the outside, and whatever you did in the sandbox didn’t work outside the sandbox. You were the one who moved from in to out, and the only thing that remained consistent was your knowledge from inside and out. In the case of an educational arena, programming is our sandbox. The problems we solve inside the sandbox are not necessarily relevant to the outside world, but they are interesting problems in their own right. Figuring out that you need to push the truck harder in the same doesn’t apply to the pavement next to the sandbox, but solving this greatly enhances our intra-sandbox play. The purpose of solving these problems is not to advance the world outside the sandbox, but to advance yourself within the sandbox. Since you are then free to move between the sandbox and the outside world, the skills you build inside the sandbox are immediately transferable to any problem on the outside. Inside the sandbox when you are learning about time-sharing the best shovel with three other children, you’re secretly learning the skills of cooperating on a team. Programming exercises work the same way: you learn the process of solving a problem, and take this problem-solving knowledge with you when you finish.</p>
<p>Why is programming an effective education?</p>
<ol>
<li>It is <strong>problem-driven</strong> and <strong>individualized</strong>. By definition, every program you write is solving a problem. Why? Because every program accomplishes a task - the problem is as simple as “I can’t accomplish this task.” For example, if I asked you to write all the factors of 10 on a piece of paper in less than 10 seconds, that’s your problem. Maybe this one is easy, but then I can ask you to do the same for the number 123456789 (still in 10 seconds). Not ready to solve that problem yet? Not to worry - there are plenty of easier problems out there waiting for you to solve them! Have an extra afternoon this week? Not to worry - you can do another problem! You can work at your own pace in solving small problems.</li>
<li>It is <strong>fun</strong>. The satisfaction of making your computer output text to you for the first time is pure joy - I still remember the time when my father taught me the “echo” command in the DOS prompt. I thought I was so cool.</li>
<li>It is <strong>safe from failure</strong>. Programming exercises are not mission-critical; if you mess up the first 100 times, no one is going to die as a result of your typo. No horrific droughts, no estrangements from relatives, no forest fires. You just take that you messed up and try again.</li>
<li>It is a <strong>community</strong>. Because there are countless others solving programming problems (in Python), you can always ask a question.</li>
</ol>
<h2 id="python-is-the-answer">Python is the Answer</h2>
<p>When you start to learn programming, why start with Python in particular? A few reasons:</p>
<ol>
<li>Python is industry standard. If you learn / master it and want a software engineering job, this is one step. Google and YouTube both have sections of their back-end software written in Python.</li>
<li>There is a large community of developers in Python. Sharing, commenting, looking at other’s code is exactly the way to learn more. (See educational criterion number 4 from above)</li>
<li>There are scores of libraries written in Python to solve many tasks. There are new tools and libraries being developed every day, so you can automate any kind of task you can think of in Python. The fuzzywuzzy library implements fuzzy search; the Youtube-dl package lets you download YouTube videos; the this package shows the text of “The Zen of Python” on the screen; etc.</li>
<li>Python reads like English - if there is any language whose code you can look at and just read, it is Python. For example:</li>
</ol>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="k">for</span> <span class="n">number</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">):</span>
<span class="k">if</span> <span class="n">number</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"positive"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"negative"</span><span class="p">)</span></code></pre></figure>
<p>What does this program do? It looks at each number in the range of numbers from -4 to 5 (non-inclusive), then checks whether the number is greater than zero or not, printing a message according to that property. Look, English!</p>
<h2 id="why-you-should-learn-to-program-now">Why You Should Learn to Program Now</h2>
<p>For the average person, programming is the gateway to automation. For engineers, programming is one of many tools of the trade. For data scientists, programming is THE tool. Working at your own pace on small problems, with repetitions approximately weekly, you will train yourself in the art of problem solving and expand your confidence in solving ever larger problems. In your own ventures, in your own disciplines, in your own lives, you can make a difference.</p>
<h2 id="getting-started">Getting started</h2>
<p>Want to get started? Start with <a href="/exercise/2014/01/29/01-character-input.html">Exercise 1</a>, or visit our <a href="/resources-for-learners/">resources for learners</a> page to find Python books, courses, and online resources to help you along your journey.</p>