• Python List Comprehension

    Python List Comprehension

    I’ve been spending time with Python recently and am beginning to really like some of the language’s features. List comprehension creates a list by evaluating an expression on each item in each list, from left to right. It combines an expression and a loop:

    >>> [ord(letter) for letter in 'example']
    [101, 120, 97, 109, 112, 108, 101]

    Apply a condition :

    >>> [ord(letter) for letter in 'example' if ord(letter) < 112]
    [101, 97, 109, 108, 101]

    It’s useful for combining lists:

    >>> [(letter, number) for letter in 'ab' for number in '12']
    [('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')]

    Pimoroni’s Rainbow Hat introduction has an example to cycle colours on the LED rainbow:

    for i in range(101):
        h = i / 100.0
        r, g, b = [int(c * 255) for c in colorsys.hsv_to_rgb(h, 1.0, 1.0)]
        rh.rainbow.set_all(r, g, b)
        rh.rainbow.show()

    This is a little hard to follow but we’ll break it down. Hue, Saturation and Value (HSV) represents colour using three values between 0.0 and 1.0 creating a colour “wheel” that is easy to cycle on the LED. Unfortunately, the LED combines red, green and blue. The Colorsys library can convert between the two.

    • The expression is int(c*255)
    • The loop is for c in colorsys.hsv_to_rgb(h, 1.0, 1.0)

    The h=i/100 is giving a range of values from 0.0 to 1.0 in 0.01 steps (we could use a list comprehension too [i/100 for i in range(101)]).

    So, let’s look at a snapshot, where h=1.3:

    >>> colorsys.hsv_to_rgb(0.13,1.0,1.0)
    (1.0, 0.78, 0.0)

    Which the list comprehension converts to:

    >>> [int(c*255) for c in colorsys.hsv_to_rgb(0.13, 1.0, 1.0)]
    [255, 198, 0]

    Giving us the RGB value needed.


  • Using Threading rather than Thread

    Using Threading rather than Thread

    In an earlier post, I used Threads but the thread module in Python when I should be using threading. The documentation for threading says it builds upon the thread module (renamed _thread):

    This module provides low-level primitives for working with multiple threads (also called light-weight processes or tasks) — multiple threads of control sharing their global data space. For synchronization, simple locks (also called mutexes or binary semaphores) are provided. The threading module provides an easier to use and higher-level threading API built on top of this module.

    That makes sense, so I should be using the threading module. So why is there a leading underscore on thread? The Style Guide (PEP 8) says it’s a weak internal use indication and that for example modules with an underscore are not imported when using an asterisk.

    There are two ways to use this module. Define a subclass and override the run method or to use the Thread class’s default run method. I’ll use the second method here.

    The Python 2.x code I was using looked like this:

    import thread
    thread.start_new_thread(scroll, (text,))

    The new code:

    import threading
    def scroll(text):
        print(text)
    text = 'Example text'
    thread = threading.Thread(target=scroll, args=(text,))
    thread.start()

    This isn’t that different, but it is a lot more readable. The arguments are explicit and there’s no ambiguity.

    Fluent Python (Ramalho, 2015) suggests using concurrent.futures package with Python 3.x. ThreadPoolExecutor and ProcessPoolExecutor implement interfaces to submit threads or processes respectively for execution. I’ll expand on this in a future post as it is useful to submit multiple tasks and collect results – however that’s not what is needed in this example.


  • Triangular numbers (Euler 11)

    Triangular numbers (Euler 11)

    What’s a triangular number? It is the sequence found by summing all the natural numbers, for example the third number is $1+2+3=6$. Interestingly, it counts objects arranged as a triangle.

    Melchoir, CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0, via Wikimedia Commons

    This also has closed form $T_n=\sum_{i=1}^{n}i=\frac{n(n+1)}{2}$.

    I started with a brute force approach – iterate through the triangular numbers and test if the number of divisors is greater than 500. I’m using the “numbers” package’s Sigma function to implement divisor function $\sigma x(n)=\sum{d n}d^x$ where $\sigma _0(n)$ gives the total number of factors for a given number. That requires a loop, which is going to dominate for large $n$, so $O(n^2)$.

    library(numbers)
    
    triangular.number <- function(number) {
    	number = (number * (number + 1)) / 2
    }
    
    num.factors <- 0
    i <- 1
    
    while (num.factors < 500) {
    	num.factors <- (Sigma((triangular.number(i)), k = 0))
    	print(triangular.number(i)) i <- i + 1
    }

    Not terribly efficient but it gets the correct answer. So how can we improve the algorithm? Reducing the number of times we repeat the loop would be a good place to start.

    Now, $a(n)$ and $b(n+1)$ are co-prime – the only positive integer that divides them both is 1. This has a useful property, that $lcm(a,b)=ab$. Thing is, I can’t see how to incorporate it…