views:

107

answers:

3

I am building a dating site in Django / Python. I have birthday dates and need to show what the person's Zodiac sign is based on their birthday.

Anybody done this before? What would be the most efficient way of accomplishing this?

+4  A: 

You could give them some more information about position of the planets and the stars.

import ephem 
>>> u = ephem.Uranus()
>>> u.compute('1871/3/13')
>>> print u.ra, u.dec, u.mag
7:38:06.27 22:04:47.4 5.46
>>> print ephem.constellation(u)
('Gem', 'Gemini')
DiggyF
In a perfect world, you'd be able to use the `ephem` library to find out the Zodiac sign by simply replacing Uranus with Sun in your example. However, it appears that the signs and the constellations [don't match up exactly](http://en.wikipedia.org/wiki/Zodiac#Table_of_dates). There is also an astrology-specific Python library called [oroboros](http://pypi.python.org/pypi/oroboros/20080712), but it's probably overkill.
Aram Dulyan
`oroboros` uses `ephem`.
fmark
+9  A: 

I've done this before. The simplest solution that I ended up with was an array of the following key/values:

120:Sag, 218:Cap, 320:Aqu, 420:Pis, 521:Ari,
621:Tau, 722:Gem, 823:Can, 923:Leo, 1023:Vir
1122:Lib, 1222:Scorp, 1231: Sag

Then you write the birth date in the mdd format, ie, month number (starting with 1 for January) and two digit day number (01-31). Iterate through the array, and if the date is less than an item in the array, you have your star sign.

bluesmoon
+1 - this looks like the best solution that can be done without having to install a new module.
R Samuel Klatchko
An `array` or a `dict`?
Johnsyweb
I'd use a dict for that.
Daenyth
for the lookup you could use `bisect`, see the example in http://docs.python.org/library/bisect.html#bisect.bisect .
DiggyF
Using bisect for 13 keys in function that is used not very often is little overoptimised, don't you think?Moreover log_2(13) is 3.7 so you have only 13/3.7 = 3.5 times less operations. I would be concern that one operation in bisect may take more than 3.5 times than simple loop, so you even have worse performance then.To sum up, bisect is very good suggestion form most searching cased, but this is probably not the one.
Tomasz Wysocki
@Johnsyweb: dict, yes.
bluesmoon
I would also use a dict, but like this: `d[bisect(d.keys(),121)]`, resulting in "Sag". Not so much for speed, I think it just looks better than writing a loop for that.
DiggyF
+2  A: 

Using bisect is more efficient than iterating until you find a match, but a lookup table for each day of the year is faster still and really not that big.

from bisect import bisect
signs = [(1,20,"Cap"), (2,18,"Aqu"), (3,20,"Pis"), (4,20,"Ari"),
         (5,21,"Tau"), (6,21,"Gem"), (7,22,"Can"), (8,23,"Leo"),
         (9,23,"Vir"), (10,23,"Lib"), (11,22,"Sco"), (12,22,"Sag"),
         (12,31,"Cap")]
def zodiac_sign(m,d):
    return signs[bisect(signs,(m,d))][2]

assert zodiac_sign(3,9) == "Pis"
assert zodiac_sign(6,30) == "Can"
gnibbler