(Python) PyProgram #8 - Cycling Alphabets

June 2, 2008

Kushal came down with a simple looking problem with constraints that might make solving it a bit not-a-needle-into-the-banana. As usual, me and Jacob sat down trying to solve it. Rather try finding various ways of solving it. The problem is, given one character within the range a-z or A-Z (not as a list, but from string.letters) we have to find the next character in the alphabetical order. When ‘z’ or ‘Z’ is encountered, the next alphabet returned should be ‘a’ or ‘A’ respectively. The constraint is that if or while conditions and for loops should not be used. And more importantly, the main solution should be of a single line. Though Kushal had a more mathematical solution, this is what me and Jacob managed to cook up as a more logical solution (note the ‘and’ and ‘or’ ;) ),

import string

def thenext(theletter):
    return ((string.letters.find(theletter)+1) %26) and (string.letters[string.letters.find(theletter)\
+1]) or (string.letters[string.letters.find(theletter)-25])

print "for 'a' i get: "+thenext('a')
print "for 'g' i get: "+thenext('g')
print "for 'z' i get: "+thenext('z')
print "for 'A' i get: "+thenext('A')
print "for 'H' i get: "+thenext('H')
print "for 'Z' i get: "+thenext('Z')

The solution looks like..

for 'a' i get: b
for 'g' i get: h
for 'z' i get: a
for 'A' i get: B
for 'H' i get: I
for 'Z' i get: A

(Python) PyProgram #7 - Time Object Diffs

December 14, 2007

I had two time objects and needed to find the difference of time between them. Upon Googling, querying in #python and checking the documentation, found that there is not built-in function available for this. Though there were some cookbook recipes, I wanted to write my own solution to find the difference between two datetime.time objects. Though datetime.timedelta was for time difference requirements it only has a days, seconds and microseconds property while I need hour, minute and seconds. Thus, I wrote my timediff method which accepts two time objects btime and stime where btime is a bigger time than stime (b for big and s for small ;) ), and it returns a datetime.time object for the difference time. (Why I need to have time objects? I use storm ORM ;) )

def timediff(btime, stime):

    """Difference between two datetime.time objects

    Accepts two datetime.time objects where btime > stime

    Returns a datetime.time object of the difference in time of

    the two datetime objects.

    """

    btdelta = timedelta(hours=btime.hour, minutes=btime.minute, seconds=btime.second)

    stdelta = timedelta(hours=stime.hour, minutes=stime.minute, seconds=stime.second)

    tdiff = btdelta - stdelta

    tdiffsec = tdiff.seconds

    if tdiffsec < 60 and tdiffsec > 0:

        return time(0, 0, int(tdiffsec))

    elif tdiffsec < 3600 and tdiffsec > 0:

        tdiffsplit = str(tdiffsec/60.0).split('.')

        tdiffmin = int(tdiffsplit[0])

        tdiffsec = float("0."+tdiffsplit[1])*60

        return time(0, int(tdiffmin), int(tdiffsec))

    elif tdiffsec > 0:

        tdiffhourmin = str(tdiffsec/3600.0).split('.')

        tdiffhour = int(tdiffhourmin[0])

        tdiffminsec = str(float("0."+tdiffhourmin[1])*60).split('.')

        tdiffmin = int(tdiffminsec[0])

        tdiffsec = float("0."+tdiffminsec[1])*60

        return time(tdiffhour, tdiffmin, int(tdiffsec))

    else:

        return time(0, 0, 0)

(Python) PyProgram #6 - Finding weeks of a month

November 24, 2007

My colleague had a problem, he needed to separate the dates in a month according to weeks. That is, given a month, he has to find the dates in 1st week, dates in 2nd week and so on. This is need to query and collect a weeks data for a given month. He was trying to write his own solution which we Python guys around thought was a bit non-straight forward. My other colleague Jacob sat and wrote a small Py script to order the dates per week of a given month,

from datetime import datetime, timedelta

current_date = datetime.now() year, month = current_date.timetuple()[:2]

first_day_of_month = datetime(year, month, 1)

if month == 12:

    first_day_of_next_month = datetime(year+1, 1, 1)

else:

    first_day_of_next_month = datetime(year, month+1, 1)

#Subtracting 1 day

last_day_of_month = first_day_of_next_month - timedelta(1)

#First and Last days of the month

print first_day_of_month, last_day_of_month

#Computing start and end week days

first_week_day = first_day_of_month.weekday()+1

date_range = [0]*first_week_day + range(first_day_of_month.day,

last_day_of_month.day+1)

month = []

while date_range:

    if len(date_range) >= 7:

        week = date_range[:7]

        date_range = date_range[7:]

    else:

        week = date_range

        date_range = None

     month.append(week)

for week in month:

    print week

for week in month:

    start_week, end_week = min(week), max(week)

    if start_week==0:

        start_week = 1

    print start_week, end_week

Python BoF at foss.in

November 14, 2007

I was enquiring Baiju about the Python Collective at the Bar Camp Bangalore 5, which is scheduled for this weekend, as I hadn’t seen any discussion about it in the BangPypers list. This is when Baiju asked me about having a BoF during foss.in, which I readily seconded and as per his advice, start the discussion in BangPypers list for the same. And thats why this post comes out.

We plan to have a “Python BoF” during foss.in 2007, organized by BangPypers (the Bangalore Python User Group). The discussions will happen in the BangPypers Mailing List to decide the day and time, after which I will update the tentative date and time here, as well announce it in both BangPypers and foss.in mailing lists. Hope to see a lot of Pythonians at the BoF and interesting discussions happen :)


(Python) ipython

October 31, 2007

When I was just peeping into the discussions at #python, I saw a few talking about ipython. On first look, I thought it to be Iron Python stuff but was wrong. It is an (another?) enhanced Python Shell or what we otherwise call as Interactive Python Mode. The good thing with these stuffs is you can just download and try them, not much a paining process to get them working. Hence I went for it.

Features

  • Dynamic Object Introspection : We can access docstrings, function definition prototypes, source codes of modules, source files and a lot more dynamically.

For example, after importing `os` module, typing os.path?? or os.path? gives complete source code and description of the os module respectively. Similarly `%pdoc object`gives us the object’s doctstring information.

  • Local namespace completion with TAB press.
  • Numbered input/output prompts.

In [1]: print “Hello World!”
Hello World!

In [2]: (1+2)*3
Out[2]: 9

  • User-extensible`magic` commands (type %magic for information).
  • System shell access with ! prefix.

!ls will issue the `ls` command in the system shell and print its output.

  • File system navigation with %cd command.
  • Verbose and colored exception traceback.
  • Auto-parenthesis.

>>> callable_ob arg1, arg2, arg3
and the input will be translated to this:
–> callable_ob(arg1, arg2, arg3)

  • Auto-quoting.

>>> ,my_function a b c # becomes my_function("a","b","c")
>>> ;my_function a b c # becomes my_function(”a b c”)

  • Embeddable within other python code/modules.

Installation

I always prefer the `svn checkout` way of getting the source code. We can get to know more about ipython at its home site. We can also get pythonreadline from the same site, which helps us to have features like color, tab, completion, etc. (I read somewhere that it is not needed for ipython as it implicitly has pyreadline). The following are the steps to install ipython from the svn repos as a local copy,

  1. We can get the source code by doing an svn checkout,
  2. svn co http://ipython.scipy.org/svn/ipython/ipython/trunk ipython

  3. We need to get into the checked out source directory and run the following command
  4. python setup.py install

  5. The –home option can be used to specify a directory to install the ipython, else it will install in the default python directories.
  6. python setup.py install --home /home/myuser/python/ipython

  7. If we are using –home option, then we need to add the following line into our.bashrc. Else we need to export the PYTHONPATH variable every time adding the path of our ipython/lib/python installation to it.
  8. export PYTHONPATH=/home/myuser/python/ipython/lib/python

  9. We can run ipython by executing ipython/bin/ipython from the shell (or create a link pointing to this file).

The complete documentation can be obtained as pdf as well as viewed as HTML.


(Python) Function calls for beginners

September 28, 2007

A function `call` is a callable object with a series of arguments which can be empty.

syntax : primary(arg_list['',''])
arg_list ::= positional_args [, keyword_ags][, *expression][, ** expression] |
keyword_args[, *expression][, ** expression] |
*expression [, **expression] |
** expression

positional_args ::= expression (, expression*)
keywords_args ::= keyword_item (, keyword_item*)
keyword_item ::= identifier = expression

`primary` is the callable object (function name, built-in callable method objs, class objs, methods of class instances and callable class instances)

How arguments are processed ?

1. a list of unfilled slots for formal parameters is created
2. N positional_args are placed in first N slots
3. keyword_args are placed in corrsponding slot using identifier

TypeError if a slot is already filled

4. Unfilled slots are filled with corresponding default values

TypeError if slots exist with no default values
TypeError if positional_args > formal param slots
TypeError if ketyword_args doesn’t match with formal param name unless **identifier is present

5. *expression evaluates to sequence like y1…yM and are placed as additional positional_args after x1…xN such that the call is made with x1….xN,y1..yM positional arguments
6. **expression is a dictionary contained excess keyword arguments

TypeError if **expression doesn’t evaluate to dictionary

7. *expression is processed before keyword arguments, hence unusual to use both keyword_args and *expression

A call return can be,

  • as per the return statement for a user-defined func
  • up to the interpreter for a build-in func or method
  • a new class instance for a class object
  • the user-defined function for a class instance method with the instance as the first argument
  • as per __call__() method for a class instance

Examples:

# define a function with two params, printing them as result
>>> def f(a,b): print a, b
...

# both are keyword_args
>>> f(a=1,b=2)
1 2

# both are positional_args
>>> f(1,2)
1 2

# a is keyword and b is considered positional. ERROR!
>>> f(a=1,2)
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

# a is positional and b is keyword_arg
>>> f(1,b=2)
1 2

# 1 is positional while 2 is *expr and takes as additional positional_arg for b
>>> f(1,*(2,))
1 2

# 1 is keyword for a, but 2 is also positional_arg for a. ERROR!
>>> f(a=1,*(2,))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'a'

# 1 is a keyword_arg for b, while 2 is positional_arg for a
>>> f(b=1,*(2,))
2 1

# 1 is keyword_arg for a, while 2 is specified thru **expr for b
>>> f(a=1,**{'b':2,})
1 2

# 1 is positional_arg using *expr for a, b is keyword_arg thru **expr for b
>>> f(*(1,),**{'b':2,})
1 2

# both a and b are specified as keyword_args thru **expression
>>> f(**{'a':1,'b':2,})
1 2

Original Reference (Python Reference Documentation)


Who Uses Python ?

June 5, 2007

I happen to see an interesting post in the Python mailing list. The question was to know who uses Python, other than sys-admins and web developers. And here is a consolidation of the replies till now.

  • For login scripts, locking down PCs, automating backups, GIS, and more.
  • Electrical engineering. It’s pretty handy for writing programs to talk to embedded systems using various protocols/interface (async-serial, ethernet, etc.). It’s also good for analyzing communications, analyzing performance tests for analog instruments, and so on.
  • The Technical Artists are using Python more and more for development needs.
  • For digital art (music visualization). It’s excellent for data analysis (I’ve done everything from stats on lines in an SQL database to mining flat text files of data for statistical projections of MLB baseball player performance). I know a couple of
    people who sell a double-entry accounting system written in Python, which is presumably “finance”. Web analytics is very common (I’ve seen several such projects)
  • we use Python for controlling fully automated logistics solutions (conveyors and stacker cranes), for generating PLC code etc.

There is also a very long reply on how Python has been used for Railway Computer-control Simulation which lists the use of Python 2.5 as,

  • The main database where all states are kept (signal aspects, given and actual turnout states, track occupation …). It’s a simple binary protocol using TCP; the server maintains string:int pairs in a Python dict. It’s made with Twisted and running under twistd.
  • The automatic drive controlling software of the model trains. It listens for changes of signals and track occupation and controls the model trains using a commercial digital model railroad controller attached to /dev/ttyS0. Also using Twisted/twistd, and
    pyserial.
  • Various helper scripts and little servers for small functional units (tramway reverser, level crossings)

This is the latest one I read,

  • To manage the database application, data integration, and reporting
  • to shuffle and sort important files around, to convert reports into formats necessary for various import and export functions, to reconcile data between database systems, and to maintain little text databases for various business processes.

Some other common replies includes text search, data mining and biotechnology. Nice to hear about some real time uses of Python, different from the usual administration and web stuffs. :)


PyProgram #5 - SMTP Mail Sender

May 3, 2007

Had some requirement to send mails in my project, so we were digging into the smtplib module. Thought of trying out a small script which will send mails. The example code was fine, but modified the functions and added “Subject: ” header to it. Tested it and voila it sent mails :P A rather trivial piece of code, but posting it to save it somewhere in my web space ;)

#!/usr/bin/env python

"""Command-line SMTP Mail Sender
This script can send mails provided you have an account
with an SMTP server.

The inputs have to be given at the
command line. The recepients address can be a space
separated list of emails.

The subject can be multiple lines, seperated by empty lines.
When done, end the subject with Ctrl+D to send the mail.
"""

import smtplib

# function to fetch the input from command line
def prompt(prompt):
return raw_input(prompt).strip()

fromaddr = prompt("From: ")
toaddrs = prompt("To: ").split()
subject = prompt("Subject: ")
print "Enter message, end with ^D (Unix):"

# Add the From: and To: headers at the start
msg = ("From: %snTo: %snSubject: %snn" %(fromaddr, ", ".join(toaddrs), subject))
while 1:
try:
line = raw_input()
except EOFError:
break
if not line:
break
msg = msg + line

print "Message length is " +repr(len(msg))

# connect and send the mail
server = smtplib.SMTP()
# connects to default port, if not specify it as additional argument
server.connect('mail.myhost.com')
# specify username and password
server.login('me.myhost.com','me1234me')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
# done!

PyProgram #4 - Who is on duty ?

April 3, 2007

We had an interesting problem posed in python mailing list, though it is not a very tough one. But still, practical problems are a fun to solve. This guy wanted to know how he can find which group is on duty. There are 4 group of fire-fighters each cycled on duty for a day one after another. Poor guys, they do not get any off even for holidays. The 4 groups all joined on a single day, so the start day is common for all. Based on this starting day, we have to find which group is on duty if given a particular day. This is a simple and interesting problem to solve. So, we all jumped in and used the datetime module. Here is my code dutycycle.py,

#!/usr/bin/env python
"""Data Cycle Finder
Find which group takes charge on a corresponding date.
There are four groups, each working on a 24-hour cycle
one after another. The groups work one day after another
in order, without any break for holidays.

Given a date, it is needed to find which group is on
duty. All the groups have a start date and a group
number. Hence given a date, the output should be the
group number which is on duty.

The input date is of the form dd/mm/yyyy.
"""

from datetime import date
import sys

def dutyfinder(_date):
    start = date(2007,1,1) # the duty cycle started on 1st jan 2007
    return (date.toordinal(_date)-date.toordinal(start))%4

inputdate = sys.argv[1]
indate = sys.argv[1].split('/')
enddate = date(int(indate[2]),int(indate[1]),int(indate[0]))
onduty = int(dutyfinder(enddate)) + 1
print "The group to report for duty on %s is %s" %(str(inputdate),str(onduty))

Now, we need to call this file with the input date as the argument. The starting date is set to 1st January 2007 and the input date format is dd/mm/yyyy. To find which group should report to duty on 10.01.2007,

$ python datacycle.py 10/01/2007
The group to report for duty on 10/01/2007 is 2

I had mailed the OP the code and he has thanked me for it ;)


The Zen of Python

March 21, 2007

Just finished reading an article on What is Pythonic ? by Martijn Faassen. At the end of the article there was a try this; I tried..

>>> import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly.

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Sparse is better than dense.

Readability counts.

Special cases aren't special enough to break the rules.

Although practicality beats purity.

Errors should never pass silently.

Unless explicitly silenced.

In the face of ambiguity, refuse the temptation to guess.

There should be one-- and preferably only one --obvious way to do it.

Although that way may not be obvious at first unless you're Dutch.

Now is better than never.

Although never is often better than *right* now.

If the implementation is hard to explain, it's a bad idea.

If the implementation is easy to explain, it may be a good idea.

Namespaces are one honking great idea -- let's do more of those!

(Python) Decorators

March 8, 2007

Decorators in Python are bit confusing concept to understand. It is not a standard feature generally explained in many of the Beginners’ books on Python. But, understanding the basic idea of decorators will help us in making a very good use of it. As the rule always goes, there are certain situations where decorators are highly useful but not always.

Decorators in a way of transforming functions and methods at the point where the code is declared. The point of transformation is placed just before the method’s own declaration.

To give a more clear idea, we generally put some code within a function, make use of other functions by calling them, performing some calculations or processing within the function’s body, and finally return some result or print some output.

Think of a situation where the attributes of the function get modified when the function is actually executed. That is, we start the function feeding it with a specific argument/parameter over which the function code operates. But, instead of directly passing over the input arguments to the function code, we rather try to do something with these arguments, modify them, process them and then pass it to the function as though they are untouched. Thus we make the function feel as though it is receiving the input as it is, but we are actually modifying them. The important point to note is these things happen at function execution time, just before the original function code executes.

The original proposal of Decorators as an enhancement and the discussion thereby are documented in PEP (Python Enhancement Proposal) 318. There are also few examples given to show how decorators can be implemented in general. But, for a newbie these examples are not easy yo grasp.

I myself have to thank Siddhartha and Rajeev J Sebastian for helping me with additional examples and explanations respectively, for me to understand the concept and deliver my talk during FOSS.NITC 2007.

Let me start with Siddhartha’s simple example - Decorating a custom method with a decorator which prints text around the function call.

Example 1:

def decorate(fn):
    def _decorate():
        print "Before Calling"
        fn()
        print "After Calling"
    return _decorate

@decorate
    def mymethod():
        print "Inside Function"

mymethod()

Output:

Before Calling
Inside Function
After Calling

Explanation:

A decorator is another object which expects to be fed with a function object. What the decorator does ? When the function is called, instead of allowing it to execute normally, if fetches the function object. It can modify the attributes of the function object or add new attributes. Instead it can just print some thing else and call the original function and execute it, in the middle of its own code as shown above. Just it prints the first text, calls the function which prints its own text, then it prints the text following the function call.

All of these happens at run time, when the function is actually called. Otherwise, its just a definition of another method. Thus, decorators jumps into action only when the function is actually called somewhere.

Another example might help us in understanding decorators much better. This time we will try to do something with the arguments passed to the function itself using the decorator and enjoy the fun.

Example 2:

def params(fn):
    def _inner(x):
        print "You called me with %d, but I rather called with %d" %(x,x+1)
        fn(x+1)
    return _inner

@params
def myfunc(x):
    print "I got", x

myfunc(5)

Output:

You called me with 5, but I rather called with 6
I got 6

Explanation:

The decorator params() is used to dynamically add 1 to the input argument and call the function myfunc() with the changed argument. Thus when we call the function with a value 5 for x, the decorators calls the function with a value 6. What the function expects is a input argument x and it prints it. But what to be noted is, the decorator modified the parameter passed to the function and executed it with the modified parameter.

Ok, what else we can do ? We can pass a parameter to the decorator itself and use it to perform some operation on the function over which the decorator is applied. This example illustrates such an application of decorators.

Example 3:

def adapttoinput(str):
    def _multdecor(fn):
        def _inner(a,b):
            fn(a*b)
        return _inner
    def _adddecor(fn):
        def _inner(a,b):
            fn(a+b)
        return _inner
    if str == "*":
        return _multdecor
    else:
        return _adddecor

@adapttoinput("*")
def mymethod(a):
    print "The output is", a

mymethod(2,3)

Output:

The output is 6

Explanation:

Though the example looks ordinary, one interesting point needs to be noticed. The original function mymethod() accepts a single input argument a, but if you look at the function call it was mymethod(2,3). We passed 2 input arguments 2 and 3. But, it worked out! That is what the decorator magically did. It transformed the two input arguments into a single argument and passed it to the original function. Thus, even when the function was called with 2 arguments, when it was actually executed it was given only one argument as input. The decorator made use of the string passed to it to convert the 2 arguments in function call to one argument before giving it to the function. A “*” passed to the decorator results in addition of the input arguments and anything else results in addition of the input arguments.

These are very simple examples to demonstrate what a decorator can actually do. If you want to understand where decorator can be implemented in real time code, please check Siddhartha’s example on Guard Implementation using Python Decorators.


PyProgram #3 - OOP in PyQt

December 16, 2006

Since foss.in 2006 I have got a special Interest in KDE and GUI development. Its up to such extent that I installed kubuntu-desktop in my laptop and started using it, at laeast when am home. I have also started learning PyQt, ultimately wish to learn PyKDE and contribute to KDE. I have started working with the Qt tuorial, which is in C++. So I have to write the change it to Python i.e. PyQt. Its not a much a problem, rather easy too. But, example 4 had some OOPs in it and I haven’t tried much OOPs in Python before. So, here goes my first OOP PyQt code, which I came up with a bit of struggle for some time.

The original Qt tutorial is here…


#include <qapplication.h>
#include <qpushbutton.h>
#include <qfont.h>
class MyWidget : public QWidget
{
public:
MyWidget( QWidget *parent=0, const char *name=0 );
};
MyWidget::MyWidget( QWidget *parent, const char *name )
: QWidget( parent, name )
{
setMinimumSize( 200, 120 );
setMaximumSize( 200, 120 );
QPushButton *quit = new QPushButton( “Quit”, this, “quit” );
quit->setGeometry( 62, 40, 75, 30 );
quit->setFont( QFont( “Times”, 18, QFont::Bold ) );
connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );
}
int main( int argc, char **argv )
{
QApplication a( argc, argv );
MyWidget w;
w.setGeometry( 100, 100, 200, 120 );
a.setMainWidget( &w );
w.show();
return a.exec();
}

And here is my PyQt code…


#!/usr/bin/env python
import sys
from qt import *
class MyWidget(QWidget):
“”"MyWidget is a custom widget to display a quit button.
This widget is inheritted from QWidget”"”
def __init__(self, parent=None, name=None):
QWidget.__init__(self,parent,name)
self.setMinimumSize(200, 120)
self.setMaximumSize(200, 120)
quitbutton = QPushButton(”Quit”, self, “quitbutton”)
quitbutton.setGeometry(62, 40, 75, 30)
quitbutton.setFont( QFont(”Serif”, 16, QFont.Bold))
self.connect( quitbutton, SIGNAL(”clicked()”), qApp, SLOT(”quit()”))
app = QApplication(sys.argv)
w = MyWidget()
w.setGeometry(100, 100, 200, 120)
app.setMainWidget(w)
w.show()
app.exec_loop()

The testing part of the code was how to transfer the ‘constructor’ in C++ to Python. Although Python is Object Oriented, we do not have constructor as in C++. We rather have a __init__ method, which can act as initializer, the job which the constructor does and the same reason for people to call __init__ to be the constructor in Python (which I found to be not the right way, from the Python Documentation and various other sources).

Actually, if you see the code it is pretty obvious that the Python code is easier to understand, easier to code and easier to maintain. Things are small and simple, but still your job gets done. And also, I realized that we can effectively transform (or port) an existing C++ code (or any of the many programing language) into Python code. Hope, I continue on this learning curve and learn things soon, end up writing cool Python Apps contributing to the community.


PyProgram #2 - Validating start and end dates

December 8, 2006

Time for another n00b code in Python. My colleague was trying to validate start and end dates, where start date has to be earlier (or lesser) than end date. I always love coding for n00b stuffs like this, so I decided to have some fun.

Problem: Given start_date and end_date, validate the dates for start_date <= end_date and print a message whether date is accepted or rejected.

Solution:

Logic: I tried to use simple if-else-statements for the job, so I hit with the following logic.

check year1 < year2:
yes –> oK
no –> check year1 == year2:
no –> Quit
yes –> check month1 < month2:
yes –> OK
no –> check month1 == month2:
no –> Quit
yes –> check day1 < day2:
yes –> OK
no –> check day1 == day2:
yes –> OK
no = Quit

The start_date and end_date are split into the corresponding day, month and year values held in the arrays dd1 and dd2.

First the years are compred - if year2 is greater than year1, then the flag becomes 1. Else, equality of years is checked, if no then flag becomes 0.

For equal year values, months are compared - if month2 is greater than month1, flag becomes 1. Else, equality of months is checked, if no then flag becomes o.

For equal year and month values, days are compared. If day2 is greater than day1 or if the dates are equal, then flag becomes 1. Else the flag becomes 0.

Finally, if flag is 1 then the dates are accepted and if its 0 the dates are rejected.

Code:


def checker(date1,date2):
if int(dd1[2])def checker(date1,date2):
dd1=date1.split(’-')
dd2=date2.split(’-')
flag = 0
if int(dd1[2]) < int(dd2[2]):
flag = 1
elif int(dd1[2]) == int(dd2[2]):
if int(dd1[1]) < int(dd2[1]):
flag = 1
elif int(dd1[1]) == int(dd2[1]):
if int(dd1[0]) < int(dd2[0]):
flag = 1
elif int(dd1[0]) == int(dd2[0]):
flag = 1
else:
flag = 0
else:
flag = 0
else:
flag = 0
if flag == 1:
print ‘Dates accepted’
else:
print ‘Dates rejected’

Test: Now we can check the checker() function, with various possible date values. Here is the result..

>>> checker(’29-12-2006′,’01-01-2007′)
Dates accepted
>>> checker(’20-11-2006′,’20-12-2007′)
Dates accepted
>>> checker(’20-12-2006′,’22-12-2007′)
Dates accepted
>>> checker(’20-11-2006′,’20-12-2006′)
Dates accepted
>>> checker(’20-12-2006′,’22-12-2006′)
Dates accepted
>>> checker(’24-12-2006′,’22-12-2006′)
Dates rejected
>>> checker(’24-12-2006′,’24-12-2006′)
Dates accepted
>>> checker(’24-12-2007′,’24-12-2006′)
Dates rejected

Yay! Done!

Note: This code is to just show how to code in a plain way, for the proposed logic. But, this is not the best way to code in Python. The better way is to make use of built-in modules like ‘datetime’ module, which will help in doing the same stuff in a couple of lines or code, and also thats the Pythonic way of doing things. What I intend is to just show the transformation of a logic into expected result, using a simple python code using nested if-elif-else condition. 


PyProgram #1 - Replacing contents of a string using a dictionary of replacements

November 14, 2006

Came across a nice programming problem, actually intended for an exam on Python. Was in a mood to try solving them using my ’solpa’ knowledge of Python.

Problem: Given the input string ‘aabbabccdab’, replace the characters as follows: a with l, b with m, c with n, d with o, using dictionaries. The replacement should produce a new string, instead of changing the original string.

Solution:

Create an input string

inputstr = ‘aabbabccdab’

Create a dictionary of replacement letter pairs

convdict = {’a':’l', ‘b’:'m’, ‘c’:'n’, ‘d’:'o’}

We have the input string, how to read individual letters? Try this

# for x in inputstr: print x

Now we have to read each letter to the string, find the replacement letter from the dict and replace it. Wait! Rather add it to a new string. One way is to initialize an empty list and add letter by letter to it and finally join them as a string.

outputlst = []

So, here is the python code which is going to do the replacement and append it to the list.

for x in inputstr: outputlst.append(convdict[x])

But, now we have only a list of the letters replaced from the string, while we need an output string. So, we have to join the elements of the list.

import string

outputstr = string.join(outputlst, ”)

Hmm, let us check.

print outputstr

llmmlmnnolm

Hurray!

Is there a better way than to do this ? Without using list, of course, just add the replacements to a string.

outputstrn = “”

for x in inputstr: outputstrn = outputstrn+convdict[x]

print outputstrn

Always try to do it simple, the way your are confident of getting an answer. Once you are done, have a second look of making the code small and further simple. Hope, I did come up with a decent solution. :)

With respect to Sridhar Ratna’s comment, I tried to make use of string.makestrans(). After a little help from Casanova, I could end up with a little different but a simpler solution. But am not sure how to use a dictionary of replacement letters in this method, will figure it soon :)

Module: string

Syntax: maketrans(from, to) –> string

Description: Returns a translation table, a string of 256 bytes long,, suitable for use in strings.translate. The strings from and to must be of the same length.

Code:

import string

transtr = string.maketrans(”abcd”,”lmno”)

outputstr = string.translate(”aabbabccddab”,transtr)

print outputstr

‘llmmlmnnoolm’