Sunday, June 26, 2016

A Pythonic ratio for pi (or, Py for pi :)

By Vasudev Ram

Py


Pi image attribution

A Python built-in method can be used to find a ratio (of two integers) that equals the mathematical constant pi. [1]

This is how:
from __future__ import print_function
Doing:
dir(0.0) # or dir(float)
gives (some lines truncated):
'__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 
'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real']
>>>
from which we see that as_integer_ratio is a method of float objects. (Floats are objects, so they can have methods.) So:
>>> import math

>>> tup = math.pi.as_integer_ratio()
>>> tup
(884279719003555, 281474976710656)

>>> tup[0] / tup[1]
3.141592653589793

>>> print(sys.version)
3.6.0a2 (v3.6.0a2:378893423552, Jun 14 2016, 01:21:40) [MSC v.1900 64 bit (AMD64
)]
>>>
I was using Python 3.6 above. If you do this in Python 2.7, the "/" causes integer division (when used with integers). So you have to multiply by a float to cause float division to happen:
>>> print(sys.version)
2.7.11 (v2.7.11:6d1b6a68f775, Dec  5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)]

>>> tup[0] / tup[1]
3L
>>> 1.0 * tup[0] / tup[1]
3.141592653589793
>>>
[1] There are many Wikipedia topics related to pi.
Also check out a few of my earlier math-related posts (including the one titled "Bhaskaracharya and the man who found zero" :)

The second post in the series on the uses of randomness will be posted in a couple of days - sorry for the delay.

- Vasudev Ram - Online Python training and consulting

Signup to hear about my new courses and products.

My Python posts     Subscribe to my blog by email

My ActiveState recipes



Sunday, June 12, 2016

Driving Python function execution from a text file

By Vasudev Ram



Beagle Voyage image attribution

Dynamic and adaptive systems are interesting, since they are more flexible with respect to their environment. Python itself is a dynamic language. Here is a technique which can make Python programs even more dynamic or adaptive.

This post shows a simple technique for driving or dynamically configuring, via an external text file, which specific functions (out of some possible ones), get executed in a program. As such, you can consider it as a sort of configuration technique [1] for externally configuring the behavior of programs, at run time, without needing to change their source code each time.

[1] There are, of course, many other configuration techniques, some of which are more powerful. But this one is very easy, since it only needs a dict and a text file.

Here is the code for the program, func_from_file.py:
# Driving Python function execution from a text file.
# Author: Vasudev Ram: 
# https://vasudevram.github.io, 
# http://jugad2.blogspot.com
# Copyright 2016 Vasudev Ram

def square(n): return n * n
def cube(n): return n * square(n)
def fourth(n):  return square(square(n))

# 1) Define the fns dict literally ...
#fns = {'square': square, 'cube': cube, 'fourth': fourth}
# 2a) ... or programmatically with a dict comprehension ...
fns = { fn.func_name : fn for fn in (square, cube, fourth) }
# OR:
# 2b) 
# fns = { fn.__name__ : fn for fn in (square, cube, fourth) }
# The latter approach (2a or 2b) scales better with more functions, 
# and reduces the chance of typos in the function names.

with open('functions.txt') as fil:
    for line in fil:
        print
        line = line[:-1] 
        if line.lower() not in fns:
            print "Skipping invalid function name:", line
            continue
        for item in range(1, 5):
            print 'item: ' + str(item) + ' : ' + line + \
            '(' + str(item) + ') : ' + str(fns[line](item)).rjust(3)
And here is an example text file used to drive the program, functions.txt:
$ type functions.txt
fourth
cube
fourth_power
Running the program with:
python func_from_file.py
gives this output:
$ python func_from_file.py

item: 1 : fourth(1) :   1
item: 2 : fourth(2) :  16
item: 3 : fourth(3) :  81
item: 4 : fourth(4) : 256

item: 1 : cube(1) :   1
item: 2 : cube(2) :   8
item: 3 : cube(3) :  27
item: 4 : cube(4) :  64

Skipping invalid function name: fourth_power
The map image at the top of the post, is of the Voyage of the Beagle, the ship in which Charles Darwin made his expedition. His book, On the Origin of Species, "is considered to be the foundation of evolutionary biology", and "Darwin's concept of evolutionary adaptation through natural selection became central to modern evolutionary theory, and it has now become the unifying concept of the life sciences.".

Note to my readers: In my next post, I'll continue on the topic of randomness, which I started on in this post:

The many uses of randomness.

- Vasudev Ram - Online Python training and consulting

Signup to hear about my new courses and products.

My Python posts     Subscribe to my blog by email

My ActiveState recipes

Wednesday, June 1, 2016

The many uses of randomness

By Vasudev Ram


Dice image attribution




Computer random number generators (RNGs) [1] have many uses. In a programming class I was teaching recently, a participant was surprised by a certain usage of random numbers that I showed; which I thought would be common knowledge. That made me realize that many novices, and possibly even some more experienced programmers, may not be aware of some among the many useful applications of random numbers.

That gave me the idea for this post, in which I'll show some of the ways in which random numbers are useful. The examples are in Python, but the concepts and techniques can be applied in any programming language that
has a random number generation facility.

[1] Strictly speaking, these are really pseudo-random number generators (PRNGs), but I'll call them RNGs for short.

(The Wikipedia article on random number generation has information on the difference between RNGs and PRNGs - and a lot more interesting information on random numbers in general, including their use in ancient times, e.g. the use of yarrow stalks (for divination) in the I Ching :)

Note: None of the random number uses that I will show requires advanced mathematical knowledge.

Let's start.

Import and introspect the random module from Python's standard library:
$ python
>>> import random
>>> dir(random)
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'System
Random', 'TWOPI', 'WichmannHill', '_BuiltinMethodType', '_MethodType', '__all__'
, '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_acos', '_c
eil', '_cos', '_e', '_exp', '_hashlib', '_hexlify', '_inst', '_log', '_pi', '_ra
ndom', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betava
riate', 'choice', 'division', 'expovariate', 'gammavariate', 'gauss', 'getrandbi
ts', 'getstate', 'jumpahead', 'lognormvariate', 'normalvariate', 'paretovariate'
, 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'tr
iangular', 'uniform', 'vonmisesvariate', 'weibullvariate']
>>>
We can see that the module has many functions and other attributes, such as the important mathematical constants e (_e) and pi (_pi). (Those last two are also available in the math module as e and pi.)

In this post, I'll look at some uses of one of the most fundamental functions in the module, called random(), like the module. In a following post or two, I'll look at other functions, and also other uses in different areas, including some less obvious ones.

First print its docstring:
>>>print random.random.__doc__
random() -> x in the interval [0, 1).
It returns a random float value in the half-closed interval [0, 1), which means, any x, such that 0.0 <= x < 1.0.

Here is a program, fn_random.py, that shows some uses of the random() function:
from __future__ import print_function

# fn_random.py
# A program showing various uses of the "random" function 
# from the "random" module of Python's standard library.
# Author: Vasudev Ram - https://vasudevram.github.io
# Copyright 2016 Vasudev Ram

from random import random
from random import getstate, setstate

print("Ex. 1. Plain calls to random():")
print("Gives 10 random float values in the interval [0, 1).")
for i in range(10):
    print(random())

print()

print("Ex. 2. Calls to random() scaled by 10:")
print("Gives 10 random float values in the interval [0, 10).")
for i in range(10):
    print(10.0 * random())

print()

print("Ex. 3. Calls to random() scaled by 10 and offset by -5:")
print("Gives 10 random float values in the interval [-5, 5).")
for i in range(10):
    print(10.0 * random() - 5.0)

print()

print("Ex. 4. Calls to random() scaled by 20 and offset by 40:")
print("Gives 10 random float values in the interval [40, 60).")
for i in range(10):
    print(20.0 * random() + 40.0)
Here is the program's output when run with:
python fn_random.py
Ex. 1. Plain calls to random():
Gives 10 random float values in the interval [0, 1).
0.978618769308
0.429672807728
0.807873374428
0.00775248310523
0.367435959496
0.452718276649
0.15952248582
0.183989787263
0.240112681717
0.873556193781

Ex. 2. Calls to random() scaled by 10:
Gives 10 random float values in the interval [0, 10).
8.66851830984
8.06203422551
6.68791916223
6.83023335837
2.28298961244
5.06491614858
9.27404238781
2.30473573581
7.62983863372
7.18179372151

Ex. 3. Calls to random() scaled by 10 and offset by -5:
Gives 10 random float values in the interval [-5, 5).
4.28960887925
-1.48913007202
-0.534170376124
3.36741617894
-3.50802287142
1.46218930484
-3.37237288568
-2.49675571636
-3.56593768859
-1.49924682779

Ex. 4. Calls to random() scaled by 20 and offset by 40:
Gives 10 random float values in the interval [40, 60).
56.4292882009
40.888150119
56.867782498
58.3162130934
41.642982556
40.8419833357
52.3684662857
45.3000297458
43.1515262997
52.1129658036
It shows how to scale and offset the values you get from random(), to transform them from the range of 0 to 1, to other ranges.

Notice that the values of the random numbers in the four sets of output are all different, even if you take the scaling into account. For example, the numbers in the second set of output are not the same as the numbers in the first set multiplied by 10, even though that is what we do in code for the second set. The reason for this is that the random numbers generated, cycle through a very long sequence, and so the first 10 numbers are output in set 1, the second 10 in set 2, and so on.

What if we wanted to have the same values of random numbers (except for the differences caused by scaling and offsetting) in all 4 output sets, say for the sake of some sort of consistency or repeatability in some scientific or statistical experiment? One obvious way is to save the first 10 numbers generated in the first snippet (say in a list) and use them in the following 3 snippets.

There is another way to do it, with the getstate() and setstate() functions of the module.

Put this line:
state = random.getstate()
before the snippet (Ex. 1.) that generates the first set of output.

Then put this line:
random.setstate(state)
before each of the following three snippets (Ex. 2 to 4.). That will do it, since now the same 10 random numbers will be generated by each snippet (before taking into account the scaling and offsetting).

In the next post, I'll show some other uses of random numbers, such for doing things with strings.


See also:

Pseudo-random number generator
Hardware random number_generator


The picture below, from Wikipedia, is the title page of a Song dynasty (c. 1100) edition of the I Ching.

I Ching image attribution

print ['Enjoy', 'See you soon', 'Bye for now'][randint(0, 2)] + " :)"

- Vasudev Ram - Online Python training and consulting

Signup to hear about my new courses and products.

My Python posts     Subscribe to my blog by email

My ActiveState recipes

Thursday, May 19, 2016

i18nify any word with this Python utility

By Vasudev Ram

I18Nify

While I was browsing some web pages, reading a word triggered a chain of thoughts. The word had to do with internationalization (often shortened to i18n by developers, because there are 18 letters between the first i and the last n). That's how I thought of writing this small program that "i18nifies" a given word - not in the original sense, but in the way shown below - making a numeronym out of the word.

Here is i18nify.py:
from __future__ import print_function
'''
Utility to "i18nify" any word given as argument.

You Heard It Here First (TM):
"i18nify" signifies making a numeronym of the given word, in the 
same manner that "i18n" is a numeronym for "internationalization" 
- because there are 18 letters between the starting "i" and the 
ending "n". Another example is "l10n" for "localization".
Also see a16z.

Author: Vasudev Ram
Copyright 2016 Vasudev Ram - https://vasudevram.github.io
'''

def i18nify(word):
    # If word is too short, don't bother, return as is.
    if len(word) < 4:
        return word
    # Return (the first letter) plus (the string form of the 
    # number of intervening letters) plus (the last letter).
    return word[0] + str(len(word) - 2) + word[-1]

def get_words():
    for words in [ \
        ['a', 'bc', 'def', 'ghij', 'klmno', 'pqrstu', 'vwxyz'], \
        ['the', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', \
        'lazy', 'dog'], \
        ['all', 'that', 'glitters', 'is', 'not', 'gold'], \
        ['often', 'have', 'you', 'heard', 'that', 'told'], \
        ['jack', 'and', 'jill', 'went', 'up', 'the', 'hill', \
        'to', 'fetch', 'a', 'pail', 'of', 'water'],
    ]:
        yield words

def test_i18nify(words):
    print("\n")
    print(' '.join(words))
    print(' '.join([i18nify(word) for word in words]))

def main():
    for words in get_words():
        test_i18nify(words)
        print

if __name__ == "__main__":
    main()
Running it with:
$ python i18nify.py
gives this output:
a bc def ghij klmno pqrstu vwxyz
a bc def g2j k3o p4u v3z

the quick brown fox jumped over the lazy dog
the q3k b3n fox j4d o2r the l2y dog

all that glitters is not gold
all t2t g6s is not g2d

often have you heard that told
o3n h2e you h3d t2t t2d

jack and jill went up the hill to fetch a pail of water
j2k and j2l w2t up the h2l to f3h a p2l of w3r

Notes:

- The use of yield makes function get_words a generator function. It is not strictly needed, but I left it in there. I could have used "return words" instead of "yield words".

- Speaking of generators, also see this post: Python generators are pluggable.

- The article on numeronyms (link near top of post) reminded me of run-length encoding

Anyway, e3y :)

- Vasudev Ram - Online Python training and consulting

Signup to hear about my new courses and products.

My Python posts     Subscribe to my blog by email

My ActiveState recipes

Sunday, May 15, 2016

[DLang]: A simple file download utility in D

By Vasudev Ram



Download image attribution

Hi readers,

Here is another in my recently started series of posts about D (DLang / the D language).

This is a simple download utility written in D, to download a file from a URL.

It makes use of a high-level function called download (sic) in the std.net.curl module, so the code is very simple. But it only handles basic cases; e.g. no authentication or HTTPS support.
/*
File: download.d
Version: 0.1
Purpose: A simple program to download a file from a given URL 
to a given local file. Only handles simple cases. Does not  
support authentication, HTTPS or other features.
Author: Vasudev Ram - https://vasudevram.github.io
Copyright 2016 Vasudev Ram
*/

import std.stdio;
import std.net.curl;

void usage(string program)
{
    writeln("Usage: ", program, " URL file");
    writeln("Downloads the contents of URL to file.");
}

int main(string[] args)
{
    if (args.length != 3)
    {
        usage(args[0]);
        return 1;
    }
    try
    {
        writeln("Trying to download (URL) ", args[1], " to (file) ", args[2]);
        download(args[1], args[2]);
        writeln("Item at URL ", args[1], " downloaded to file ", args[2]);
        return 0;
    }
    catch(Exception e)
    {
        writeln("Error: ", e.msg);
        debug(1) writeln("Exception info:\n", e);
        return 1;
    }
}
A makefile to build it in both debug and release versions:
$ type Makefile

release: download.d
        dmd -ofdownload.exe download.d

debug: download.d
        dmd -debug -ofdownload.exe download.d
To build the release version:
make release
To build the debug version:
make debug
A test run: download the current HN home page:
download news.ycombinator.com nyc.html
Output is in nyc.html; see screenshot below:


The line:
debug(1) writeln("Exception info:\n", e);
gets compiled into the binary / EXE only if you build the debug version.
That line prints a bit more information about the exception than the release version does.

You can also read a few posts about downloading using Python tools.

- Enjoy.

- Vasudev Ram - Online Python training and consulting

Signup to hear about my new courses and products.

My Python posts     Subscribe to my blog by email

My ActiveState recipes