Simple quiz using a dictionary.

12/12/2015

I thought I’d share a really simple program that uses Python’s “dictionary” data type.

If you want to read all about dictionaries, head over to the relevant section on python.org.

The basic idea of a dictionary is that it’s a way to store data. But instead of using indexes to identify elements in the list, we can use a wide range of different things as “keys”.

Here’s a really silly example.

a = dict()
# Use strings as key and value.
a["big"] = "huge"
# Use integers and floating point numbers.
a[5] = 8.2
a[3.14] = "pi"
# Use a tuple as the key and a boolean as the value.
a[(1,2)] = True
# Use a function as a value.
def plus1(x):
.. return x+1
..

Here’s what happens when we use those keys to extract items from the dictionary.

dict

So, as you can see, you can use plenty of different data types as the keys and values in a Python dictionary!

I am going to use a dictionary in a very simple way here. Let’s say we have to write a program that does a simple quiz. We could store questions and answers in a pair of lists, or even in a 2d list. But then we would have to access them using array notation (numbers in square brackets). With a dictionary we can use one string (the question) as the “key” which will link with another string (the “value” – in our case the answer).

Here’s the code.

"""quiz.py - simple quiz program."""

def main():
"""Set up the quiz."""

# The questions and answers are in this dictionary.
qs = {"What's the capital of England? ":"London",
"What's the third planet in the Solar System? ":"Earth",
"Who wrote \"Great Expectations\"? ": "Charles Dickens",
"Who sang \"Someone Like You\"? ":"Adele",
"Who is the current Doctor Who? ":"Peter Capaldi",
"Who is the sheriff in \"The Walking Dead\"? ": "Rick Grimes",
"Which metal is liquid at room temperature? ": "Mercury",
"Who plays Katniss in \"The Hunger Games\"? ": "Jennifer Lawrence",
"Which element combines with hydrogen to make water? ": "Oxygen",
"What is the highest mountain in the UK? ": "Ben Nevis"}

print("*** Quiz ***\n")
name = input("Please enter your name: ").title()
print()
print("\nWell done {0}, you scored {1} out of {2}.".format(name, quiz(qs), len(qs)))

def quiz(qs):
"""Returns a score. Asks questions from qs dictionary."""
score = 0;
# Use the .items() method to get the key / value pairs.
for q,a in qs.items():
if input(q).lower() == a.lower():
score += 1
print("Correct.")
else:
print("Sorry, correct answer is \"{}\".".format(a))
return score

if __name__ == "__main__":
main()

Print a Christmas Tree

12/12/2015

It’s been a long while since I posted anything here, but I have a festive program to share.

I think the comments should make it pretty self-explanatory.

Please note this will not work in Idle, you need to run it in the terminal. I have not tested it in Windows …

The output should look a bit like this.

tree_screenshot

But the coloured “baubles” should flash!

If you want to download the code, it’s on my github.

Here’s the program:

""" christmas.py 
Prints a christmas tree on the terminal using coloured and blinking characters.
Uses ansi terminal escape sequences.
The '\033[' part is the escape code. 
We pass '5;' for the colours other than green to make them blink.
The next part is the colour code and the 'm' ends the sequence.
To reset the colour we pass "\033[0m" after each character.
Python 3 version by antiloquax (2015), based on code from datamungeblog.com.
"""

from random import choice
from random import random

def main():
    """Make the tree and print it."""
    # If you change this, use an odd number.
    SIZE = 21
    print(makeTree(SIZE))

def makeTree(size):
    """Creates the tree string."""  
    # Probability that a character will be green.
    prob_gr = 0.6
    # Colour codes.
    colours = [31, 33, 34, 35, 36, 37]
    # Characters to use for decorations. Experiment with these.
    # The chr(169) and chr(174) characters may not work in all terminals
    # (extended ASCII, c and r in a circle).
    decs = ['@', '&', '*', chr(169), chr(174)]

    # Format string for printing blinking characters.
    blink_col = "\033[5;{0}m{1}\033[0m"
    # String to print a green octothorpe ('#').
    leaf = "\033[32m#\033[0m"

    # Width of the tree, will grow by 2 each time.
    width = 1
    # Initialise the tree string, with a star at the top.
    tree = "\n{}*\n".format(' ' * (size))

    """ Main Loop starts now."""
    
    """ We can't use the normal "format" centering approach:
        ("{:^nn}".format(string) where "nn" is the width of the line), 
        with these ansi codes. This is because Python sees the strings as being
        more than one character long (15 & 10 for baubles and leaves)."""

    # Loop from (size - 1) down to 0, using the counter as the padding size.
    for pad in range(size - 1, -1, -1):
        # Increase the width of the tree by 2.
        width += 2
        
        # Put the characters for the line in "temp".
        temp = ""
        for j in range(width):
            # Make some leaves.
            if random() < prob_gr:
                temp += leaf
            # And also some baubles.
            else:
                temp += blink_col.format(choice(colours), choice(decs))

        # Add that string to the line, with padding.
        tree += "{0}{1}\n".format(' ' * pad, temp)

    # Add a "trunk" of 2 lines and return.
    return tree + "{0}{1}\n".format(' ' * (size - 1), "000") * 2

if __name__ == "__main__":
    main()

My other blog …

04/10/2013

I have not been posting on here as much lately as I have set up another blog.

cscresources

This is a one-page blog on which I put links for you to download sample code with notes in .pdf form on a range of topics.

Today I have just added an article (plus sample programs) exploring four classic methods of enciphering messages.

Please check it out!

Knuth TAOCP, 1.4.2, ex. 7

13/06/2013

I have been reading Knuth’s classic work The Art of Computer Programming. I have been doing some of the exercises in a machine language (ARM assembly code for the Raspberry Pi). You can find those resources on a one-page blog I have created. It’s here.

This exercise, I chose to do in Python!

Simple Encode & Decode (Python)
Knuth, TAOCP, vol. 1, 1.4.2 ex. 7

The Task

This simple exercise in encoding and decoding comes in a section on coroutines, but works quite nicely using plain old Python functions. The idea is that we provide a string of characters which can contain only letters and numbers and which is terminated with a full stop.

For each character of the input, if the character is a digit (let’s call it i), then we write the following character i + 1 times (whether it is a digit or a letter). If the character is a letter, we just write it to the output once. Here’s a sample input (not the same as given by Knuth).

Knuth TAOCP 1.4.2
String: 2A0B345CDE67F1G1H0I5JK.

The output is arranged into groups of three characters separated by a space:

AAA B44 44C CCC CCD E77 777 77F GGH HIJ JJJ JJK.

The task Knuth sets is to write a program that will reverse the process. But first it makes sense to write one that performs the encoding.  I’ll start with the nuts and bolts part:

# encoder.py
# from Knuth vol. 1, 1.4.2 (p195)

def main():
    print("Knuth TAOCP 1.4.2")
    a = input("String: ")
    print(prepare(process(a)))

if __name__ == "__main__":
    main()

The main work happens in two functions, process() and prepare():

def prepare(string):
    output = ''
    count = 0
    for ch in string:
        if count == 3:
            output += ' '
            count = 0
        output += ch
        count += 1
    return output + '.'

This is very simple, it takes the output from process() and adds the spacing, plus the final full-stop. It’s important to add the spacing before adding the character, or you could end up with an unneeded space at the end.

Process() itself is fairly simple.

def process(string):
    output = ''
    i = 0
    temp = string[i]
    while temp != '.':
        temp1 = string[i+1]
        if temp.isalpha():
            output += temp
            i += 1
        elif temp.isdigit():
            output += temp1 * (int(temp)+1)
            i += 2
        temp = string[i]
    return output

First we set things up before we enter a loop. Then, in the while loop we add characters to the output string according to the rules of the encoding.

A Possible Solution

Once again, I’ll give you the boring bits first.

# decoder.py
# Knuth 1.4.2, ex. 7

def main():
    print("Knuth 1.4.2, ex. 7")
    a = input("String: ").replace(' ', '')
    print(process(a))

if __name__ == "__main__":
    main()

I’ve taken advantage of the handy Python replace() function to strip out the spaces. This program only has one other function, which I have called “process()”.

def process(string):
    i = 0
    output = ''
    temp = string[i]
    while temp != '.':
        i += 1
        count = 0
        while temp == string[i+count]:
            count += 1
        if count:
            output += str(count) + temp
            i += count
        else:
            output += temp
        temp = string[i]
    return output + '.'

Once again, I place the first character into a variable called temp before entering the while loop. I update temp with the next character at the end of the loop and this makes it easy to check for when we have finished.  Nested within the main while loop is another while loop that counts how many times a character appears in the input string. Knuth specifies that he doesn’t want zeroes to appear in the final string, so we only add a number to the output if it is over 1.

Conclusion

This is one of Knuth’s simpler examples, but it’s quite a nice one.

RSA Algorithm

16/01/2013

I have put together some short articles with sample code, all based on mathematical algorithms in Python.

Series One

1: A. M. Legendre, exponentiation by successive squaring.
2: Heron of Alexandria, square roots
3: Peano arithmetic
4: Zeller’s congruence
5: Factorial
6: Fibonacci numbers
7: Euclid’s GCD & prime factors
8: Eratosthenes’ Sieve and the Miller-Rabin algorithm
9: Pascal’s triangle
10: Tau using Gregory and Euler’s equations

Series Two

1. Newton’s method for nth roots.
2. Primes revisited
a) faster Miller-Rabin
b) Lucas-Lehmer number
3. A Little Number Theory
a) Ramanujan’s Highly Composite Numbers
b) Ramanujan and Hardy – roundness
c) Pythagoras – perfect numbers
d) Pythagoras – friendly numbers
4. Pi
a) Euler’s method for calculating Pi
b) Cesaro / Monte Carlo method
5. The RSA algorithm

The .zip file is here.

As a little taster, here is the code of my RSA algorithm program. You can copy and paste it and have a play and download the .zip file to read my notes in the pdf file.

# rsa.py - demo of the RSA algorithm

def main():
    n = e = d = 0
    while 1:
        print("""
    1. Set Public Key
    2. Encode
    3. Decode
    0. Quit
    Your choice? """, end = "")
        choice = int(input())
        if not choice:
            return
        if choice == 1:
            n, e, d = set_keys()
        if choice == 2:
            if not n:
                n = int(input("Public Key: "))
                e = int(input("e: "))
            encode(n, e)
        if choice == 3:
            if not d:
                n, e, d = set_keys()
            decode(d, n)

def set_keys():
    """This fuction asks for 2 primes.
    It sets a public key and an encoding number, 'e'."""
    p = int(input("p: "))
    q = int(input("q: "))
    n = p * q
    m = (p - 1) * (q - 1)
    e = get_e(m)
    print("N = ", n, "\ne = ", e)
    d = get_d(e, m)
    while d < 0:
         d += m
     return [n, e, d]

     def encode(n, e):
     """This function asks for a number and encodes it using 'n' and 'e'."""
     while 1:
         c = int(input("Number to encode: "))
         if not c:
             return
         print(pow(c, e, n))

 def decode(d, n):
     """This function asks for a number and decodes it using 'd' and 'n'."""
     while 1:
         c = int(input("Number to decode: "))
         if not c:
             return
         else:
             print(pow(c, d, n))
     
  def even(x):
     """True if x is even."""
     return x % 2 == 0

  def get_e(m):
     """Finds an e coprime with m."""
     e = 2
     while gcd(e, m) != 1:
         e += 1
     return e

 def gcd(a,b):
     """Euclid's Algorithm: Takes two integers and returns gcd."""
     while b > 0:
        a, b = b, a % b
    return a

def get_d(e, m):
    """Takes encoding number, 'e' and the value for 'm' (p-1) * (q-1).
    Returns a decoding number."""
    x = lasty = 0
    lastx = y = 1
    while m != 0:
        q = e // m
        e, m = m, e % m
        x, lastx = lastx - q*x, x
        y, lasty = lasty - q*y, y
    return lastx

if __name__ == "__main__":
    main()

You can download a .zip file with the other short articles and programs here.

Enjoy!

Latest Python tutorial. System arguments and stuff.

27/09/2012

Watch “Python Tutorial 13: print() and strings” on YouTube

11/08/2012

Watch “Python Tutorial 12: Turtle Graphics” on YouTube

11/08/2012

Watch “Python Tutorial 11: Peano Addition” on YouTube

11/08/2012

Video 10. Finding Square Roots.

10/08/2012