Wednesday, October 5, 2011

A Gotcha with squaring on both sides..

One of the things we often do while solving equations is square on both sides of the equation. Until today, it never occured to me that one could introduce extraneous solutions by doing so. Here is a simple example. Consider the equation .

Squaring on both sides, we have: , which leads to solutions: . Here, is an extraneous solution as a result of squaring on both sides. Be mindful of this fact when you solve equations.

Tuesday, August 2, 2011

Dream of death

Today i had a very scary dream. I owed somebody a debt, and he was going to kill me. I kind of get cornered on a huge staircase, and he was gonna push me from the top. Moments before throwing me, I ask him to give me some time (1 min or so), just so that i am prepared (I know its silly, but that's how the dream went).

So, here I was, hanging from the top of a huge staircase, and i began to reflect..."Is that all there is to my life?, I wanted to do so much...None of what i am doing right now seemed significant - acads, job, publications - none of them mattered. I reflected on how i spend most of my time keeping myself busy, never realizing that this moment would come"...it all seemed pointless. Luckily, I managed to wake up and shake off my fear...Strangely though, in the last moments of the fall, i lost all fear. I dont recall why.

So, I've decided. From Aug, I am gonna devote 2 hrs to myself. Do whatever i wanted...even if it means to just sit, or stare blankly at the stars..

On a totally unrelated note, I think this will make a fine novel. A novel that describes the thoughts of this fictional character who is going to die within a minute.

Tuesday, May 24, 2011

Android Fix

Press Volume up and power button to enter fastboot mode.
Go to device manager.
Select the android device with an ! mark, right click, update driver.
Select "Browse my computer for driver software"
Select :Let me pick from a list of devices on my computer"
Select ADB bridge, install driver.

PS: If you're using vista or windows 7, make sure your environmental variables are set up, and most importantly, launch your command prompt as admin.

Run "fastboot oem unlock"
That should do it..

Saturday, January 15, 2011

Facebook hacker Cup Round 1A - Power Overwhelming

The question goes something like: "You are to inflict mazimum damage to the zerg army. There are two types of units - Warrior and Sheild. Warriors do damage every second, while a sheild protects your entire army for one second. Your army is instantly overrun after the sheild generators expire. Given G cost to build a sheild, W cost to build a warrior and total money M, how many sheilds would you build?"

Let X and Y be the optimal number of generators and number of warriors to be built respectively. Lets take a simple example. Suppose sheilds and warriors both cost 1 unit and you have total money of 5 units. What is the optimum value of X and Y? It'd be optimum if you can inflict maximum damage. With 5 units of money, you can buy sheilds/warriors in the following combinations.

X
Y
Damage
1
4
4
2
3
6
3
2
6
4
1
4

Assuming that a warrior does D damage per second, with 4 warriors and 1 shield, they do 4D damage. With 2 shields and 3 warriors they do 3 + 3 = 6D damage. So in general, with X generators and Y warriors, the damage inflicted is X * Y * D. Therefore our goal is to maximize the product X * Y.

The cost to buy X generators is X * G. Similarly, the cost to buy Y warriors is Y * W. Since we are limited by M amount of money, X and Y must satisfy X * G + Y * W <= M. This can be represented as a line and the inequality encapsulates a region, both of which are shown in fig 1.

Fig 1. Geometric representation
For X + Y <= 5, the optimal points are (2,3) and (3,2). You can also try other examples, but you'll eventually notice that X*Y is maximum at the mid-point of the given line. G*X + W*Y <= M is just a general representation of the line. Putting Y=0, we get the intersection with X axis as M/G. Similarly, with X = 0 we get Y = M/W. The mid point is given by (M/2G, M/2W). Therefore optimal number of shields is given by M/2G. However, M/2G must be an integer. Taking floor(M/2G) should suffice as it always ensures that the given region falls within the shaded region.

However, I didn't upload this solution as i was confused with the incorrect test cases :(
Wasted my 2.5 hours.

Tuesday, January 11, 2011

A Gotcha with function minimization using genetic algorithms

Tyically, a genetic algorithm works by the notion of maximizing the fitness. Consider a function y = x, which is to be minimized in the interval [-5, +5]. One approach is use 1/x as the fitness function. Intuitively, by maximizing y = 1/x, we are minimizing y = x. However, a plot of y = 1/x reveals some serious flaws.

Figure: Plot of y = 1/x

If we move from the right, the maximum occurs at x = 0 instead of x = -5. Why? Probably because 1/x is not differentiable at x = 0. Therefore, it is safe to use y = -x as the fitness function.

In general, if we are seeking to minimize Y = F(X), then it is safe to use Y = -F(x) as the fitness function.

Facebook Hacker Cup: A Geometric Approach to Double Squares Problem

Given an integer N, we need to find the number of integral pairs (x, y) such that x^2 + y^2 = N.
n can range from [0, 2147483647] and there can be a max of 100 such numbers in the input file.

From elementary geometry, we know that x^2 + y^2 = r represents a circle centered at (0,0) with a radius r. Therefore, x^2 + y^2 = n represents a circle with radius n. This is illustrated in figure 1. Now the problem is to find all possible solutions to this equation (in the first quadrant) where x, y are integers.

Figure 1

Bruteforcing all possible integral pairs of (x, y) upto n is equivalent to searching within the geometric space (grey rectangle) illustrated in fig 2.

Figure 2
Algorithmically this approach takes O(n^2) time.Consider the sample input as shown below (this was the file I received)
20
1105
65
2147483646
1257431873
25
1000582589
1148284322
5525
0
1475149141
858320077
1022907856
1041493518
3
1215306625
372654318
160225
5928325
2147483643
1538292481
On my machine, brute force approach takes approx 14 hours (!!!) to solve this input. Obviously Facebook wasnt kidding when it hinted: "Too hard to bruteforce, switching to dp". Clearly, we are exploring a lot of unwanted points. One obvious way to improve this is to explore points bounded by the circle as shown by blue shaded rectangle in fig 3.


Figure 3

This is equivalent to looping x and y from 0 to n. This makes sense because x or y can never exceed . For example, with n = 25, if x = 5, y = 0 and vice versa. This reduces the complexity from O(n^2) to O(n) reducing execution time from 14 minutes to 80.5 sec!

Can we do any better? Why are we even exploring the blue rectangular region? Its sufficient if we examine all points on the arc of the circle in the first quadrant. i.e., we can increment x = 0 to x' (if x' is irrational number, its safe to use ceil(x')) and examine if the corresponding y points on the circle is an integer. y can be calculated using sqrt(n - x^2). Y is an integer if floor(y) == y. As illustrated in figure 4, all the points to the left of the line y=x is the mirror image of the points to the right. i.e, if we find a point, say (3, 4) to the left of y=x, then we will find a mirror image at (4, 3). Since the problem doesn't differentiate between these two. It is sufficient if we iterate x until the point x'. x' is given by .

Figure 4

With this, the complete algorithm in JAVA is listed below:

private static int getNumSumSquares(int n) 
{
if(n==0)
return 1;

int iterations = (int) Math.ceil(Math.sqrt((n * 1.0)/2));
double y;
int count = 0;
for(int x=0; x <= iterations; x++)
{
y = Math.sqrt(n - (x*x));
//check if y = int.
if(Math.floor(y) == y)
count++;
}
return count;
}
This algorithm works in O(sqrt(n/2)) ~ O(sqrt(n)). This is a huge improvement over the naive approach. With these improvements, it just takes 0.047 secs to execute!

Wednesday, December 22, 2010

Open AL, Adobe Director - No sound in projector [FIX]

One of the most annoying thing about Adobe Director is its lack of support. Open AL Xtra enables director to use OpenAL runtimes for 3D sound manipulation. Unfortunately, in a projector/exe, it doesn't play any sound. This issue was pointed out at multiple forums (here and here), without any fix so far. After struggling for nearly 4-5 hrs, I finally figured it out. The solution couldn't be any simpler. Just include these two xtras in the projector.

- Mix Services
- Sound Import Export

I got he hint from playFile() documentation for Director. It mentions the use of "Correct Mix Xtra" to play sound properly.

Tuesday, December 7, 2010

Recenberg 1/5th success rule applied to life..

For those who are not familiar, Rechenberg's 1/5 rule refers to adaptive mutation in evolutionary strategies (ES). It says that the ratio of successful mutations to all mutation should be 1/5. Deriving from this idea, if you get too successful (i.e., more than 1 out of 5 tries) then you're converging too fast to a local optima (aka safe options) and will result in stagnation later on. So, don't run after too many successes. Ideally, at-least according to Rechenberg, one should try 1 safe thing for every 4 risky things in life to optimally balance stagnation vs. growth.

Thursday, November 18, 2010

Flaw with patent law?

Math functions cannot be patented. Imagine sin, cos being patented, that'd be crazy right. Ironically computer programs can be patented. It has long been proved that computer programs are equivalent to mathematical functions. Does anyone realize its the same as patenting math functions?

Wednesday, November 17, 2010

Kleiber's Law

Last week, I happened to read about Kleiber's law while browsing through literature on natural evolution. Its implications are really fascinating. It establishes a relationship between mass and metabolism as:
Metabolism is ultimately linked to the number of heartbeats (heart pumps oxygenated blood, which is responsible for metabolism). Therefore, #heartbeats is proportional to the mass. Also, smaller creatures have high metabolism (heat generated per unit volume) and therefore have faster heart rate.

Curiously, the number of heartbeats per lifetime tends to be constant. Thus, bigger animals live longer as their heart beats slower. Flies on the other hand have shorter lifespan because of high metabolism (smaller mass).

Come to think of it, if we have fixed number of heartbeats, wouldn't running/exercising make us die faster? We are spending more heartbeats per second and it makes perfect sense. Then why is it that people who exercise live longer? The answer is simple...I'll let you think about it.

Friday, October 8, 2010

The paradox...

Newton made calculus to simplify mathematics...a true paradox!

Friday, September 24, 2010

Adding class attributes at runtime :O

The use is kind of hard to describe. In some situations, it makes more sense to add attributes to an instance at runtime. One example would be to perform optimizations at runtime (Maybe I'll describe a solid example at a latter time).

The trick is to use a HashMap to store property name and value pair. For ease of use, I defined a class 'Bufferable' with this capability. Any class extending 'Bufferable' should inherit dynamic attribute feature.

/**
* A Utility class to support addition of new properties to a java bean
* at the runtime. Extend your class with this to make it bufferable. It is
* useful if you want to associate certain properties with an object and
* maintain the OOP nature of your code.
*
*

This class extends AbstractSerializableBean
* for serialization and property change support.
*
* @author Ragha
* @see AbstractSerializableBean
* @version 1.0
*/
public class Bufferable extends AbstractSerializableBean
{
private static final long serialVersionUID = 506835437375346326L;

/**
* This map is used to store property name and object as key-value pairs.
*/
private HashMap buffer = new HashMap();

/**
* This method is used as a getter for the associated property in the
* buffer.
*
*

You must typically create the property using
* {@link #createPropertyInBuffer(java.lang.String) createPropertyInBuffer(...)} method
* before using this method.
*
* @param property The property to be used
* @return The value of the property.
* @throws java.lang.IllegalArgumentException If there is no such property.
*/
public Object getValueFromBuffer(String property)
throws IllegalArgumentException
{
if(buffer.containsKey(property))
return buffer.get(property);
else
{
throw new IllegalArgumentException("Property: '"+property+"' " +
"does not exist...");
}
}

/**
* This method can be used as a setter for the associated property.
* in the buffer.
*
*

You must typically create the property using
* {@link #createPropertyInBuffer(java.lang.String) createPropertyInBuffer(...)} method
* before using this method.
*
* @param property The property value to be set
* @param Value The value to be set
* @throws java.lang.IllegalArgumentException If there is no such property
*/
public void putValueInBuffer(String property, Object Value)
throws IllegalArgumentException
{
if(buffer.containsKey(property))
buffer.put(property, Value);
else
{
throw new IllegalArgumentException("Property: '"+property+"' " +
"does not exist...");
}
}

/**
* Creates a new property in the buffer. Once the property is created,
* it can be get or set using the
* {@link #putValueInBuffer(java.lang.String, java.lang.Object) putValueInBuffer(...)} and
* {@link #getValueFromBuffer(java.lang.String) getValueFromBuffer(...)} methods
*
*

It is recommended that you use Classname-property name as property
* string to avoid conflicts with other existing property names...
*
* @param property The property name to be associated with the buffer.
* @throws java.lang.IllegalArgumentException If the property name already exists.
*/
public void createPropertyInBuffer(String property)
throws IllegalArgumentException
{
if(buffer.containsKey(property))
{
throw new IllegalArgumentException("Property: '"+property+"' " +
"already exists...");
}
else
{
buffer.put(property, new Object());
}
}

/**
* This method can be used to check if a given property already exists.
* @param property The property to be checked.
* @return true, if the property exists.
*/
public boolean isPropertyInBuffer(String property)
{
return buffer.containsKey(property);
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Bufferable other = (Bufferable) obj;
if (this.buffer != other.buffer && (this.buffer == null || !this.buffer.equals(other.buffer))) {
return false;
}
return true;
}

@Override
public int hashCode() {
int hash = 3;
hash = 79 * hash + (this.buffer != null ? this.buffer.hashCode() : 0);
return hash;
}
}

Everything should look pretty obvious except for why i am extending my class with AbstractSerializableBean. Well, this is done in order to make the class Serializable. The code for AbstractSerializableBean should make things clearer.

/**
* This subclass enhances {@code AbstractBean} by implementing the
* {@code Serializable} interface. {@code AbstractSerializableBean} correctly
* serializes all {@code Serializable} listeners that it contains. Implementors
* that need to extends {@code AbstractBean} or one of its subclasses and
* require serialization should use this class if possible. If it is not
* possible to extend this class, the implementation can guide implementors on
* how to properly serialize the listeners.
*
* @see AbstractBean
* @author Ragha
*/
public class AbstractSerializableBean extends AbstractBean implements Serializable
{
private static final long serialVersionUID = -3459406004204097480L;

protected AbstractSerializableBean()
{
super();
}

private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();

for (PropertyChangeListener l : getPropertyChangeListeners()) {
if (l instanceof Serializable) {
s.writeObject(l);
}
}
s.writeObject(null);
}

private void readObject(ObjectInputStream s) throws ClassNotFoundException,
IOException {
s.defaultReadObject();

Object listenerOrNull;
while (null != (listenerOrNull = s.readObject())) {
if (listenerOrNull instanceof PropertyChangeListener) {
addPropertyChangeListener((PropertyChangeListener) listenerOrNull);
}
}
}
}
That's it...pretty straight forward isn't it..

Predicting hand position on the keyboard by observing random text \m/

Today, I was just typing some nonsense keys on my keyboard and happened to observe something interesting. Below is a uniform random sample of what I typed:

gh
jgh
jg
hjg
hjg
hjg
hjg
hjg
hkg
hjg
hg
jg
hjg
hjg
hg
hjg
hg
hjg
h
gh
gh
ghj
ghj
ghj
g
hjg
khg
hg
hg
hg
hjg
hjg
hjg
hjg
h
ghj

Notice how 'h' repeats a lot of times. It so happens that my middle finger was on 'h'. So, is frequency somehow linked to the length of finger? Turns out I was right. See table below. I used the keys G, H, J, K. My index finger was on G, middle on H, ring finger on J and little finger on K.

Character (Ordered by frequency)
Actual Finger on char
Finger (Ordered by length)
H
Middle
Middle
J
Ring
Ring
G
Index
Index
K
Little
Little

You can try this on your own. Place your fingers on the keyboard (horizontally, any other orientation complicates the situation as relative length changes).

Probability theory says that the chance of occurrence of G, H, J or K is 1/4. But I think that in this case, probability is somehow weighted, in a sense that it is proportional to the length of the finger.

So, what's the use of all this?
  1. I wasted your time...haha!
  2. You can predict the hand position based on random text...duh!
  3. Its cool!
  4. See 1
Is it of any use?
I guess not, that explains the label 'lame observations'. But who cares?

Thursday, August 12, 2010

P vs NP solved?

Vinay Deolalikar, an Indian scientist @ HP Labs claims to have proved P != NP. This is a significant breakthrough and is of great importance to Computer Scientists. A detailed problem description can be found at http://www.claymath.org/millennium/P_vs_NP/pvsnp.pdf


Note: This is not the final version and is currently undergoing intense peer review.

If his claim holds true, two clay math problems will have been solved! This is exciting!

Saturday, July 24, 2010

Are some people more intelligent than others? - A Mathematical Perspective

People consider some to be more intelligent than others. For example, most of us would agree if I consider newton or Einstein to be more intelligent than you. But is this really true? First off, what is intelligence? At birth everyone is (more or less) at the same level. Then why is it that some people are good at studies, while some just aren't?

In my opinion, intelligence is all about making rational decisions given the information/knowledge you possess. People are different because the definition of being rational is different for each of us. For some of us, the act of crossing the road carefully might be rational. For others, most rational thing is to cross the road as quickly as possible. These beliefs are based on prior experiences. Someone who has witnessed a road cross accident might prefer to cross it carefully. Those who got fired because of being late might consider a hush hush approach towards crossing.

Bottom line: People are different because of different experiences they possess. This can actually be explained mathematically by a principle most of us are familiar with. Its called 'Bayes Rule'. Bayes rule seeks to find a hypothesis h with high probability given an observation D. Imagine this: You go to your kitchen, find a chair that was used to reach a cookie jar which is now empty. This is observed data D. Probability of this happening is P(D). Now, you can have a set of hypothesis h belonging to set H (representing all possible hypothesis). For instance h1 can be "My daughter must have stolen the cookie". h2 = "A thief stole a cookie as he was hungry". We don't know which of these are true, all may be equally likely. However if we did observe our house to be messed up (typical indicator of stealing), it increases chances of h2 to be true. This rule may be summarized mathematically as:


Our definition of rationality is based on how our knowledge is updated by this rule. By our experiences, we form various P(D)'s and P(H)'s that direct our thinking.

Back to the original question: "Are some people smarter than others by birth?". According to bayes rule "NO". It is our experiences that lets us update probability distributions of likelihood of events/hypothesis. These probabilities guide our actions. If someone makes an intelligent choice despite this, then he/she just got lucky.

Einstein and Newton are intelligent because of their experiences. Some take their experiences for granted. For instance, most of us would just pick up and eat the apple if it fell on our head. Instead, newton reasoned as to why it happened. Is this an indicator of superior intellect? He decided to do a different action (reasoning instead of eating) which is a manifestation of past experience. He must have observed/experienced that its rewarding when you reason every small aspect.

Why do some people learn faster than others? Is it because of genetics? If so, it is again a propagation of ancestral experiences. It might be the case that they worked hard in their childhood (more experience), thereby improving their intellect. Hence, they don't have to work as hard as you to pick things up.

So, in conclusion: "All people are born with the same intellect. It is their experiences that define them. To some extent you decide your experiences, so you control how intelligent you want to be."

Tuesday, July 20, 2010

Validation framework for adobe director

Validation can be a real pain in the ass. After all no developer likes doing labor tasks. With Java, there are many excellent validation frameworks. To know about my take on validation with java see this article. Adobe director however doesn't have anything like it. So i decided to go ahead and make a simple framework in lingo.

Lets start with usage point of view. We need the name of text field, type of validator (regex, length etc..) and the error message when validation fails. Lets represent this as a list L = {"text field name", "Validator name", "error msg"}. To keep it simple, I only consider validation on text fields (I could have extended it, but it'd make the code look ugly, I wanted to keep it simple. Also, 99% of validation is on text fields)

Its obvious that a field can have multiple validators. Also, it'd be nice to validate everything in one call. So we can have input as List {L1, L2, ...Ln), where Li aforementioned list format.

But validators can have parameters. For example length validator can have 'length' parameter. So L should be List("text field name", List ("validator name", param1, param2, ...), "error message"). From the usage point of view we could have something like:
oValidator = new(script "ValidationUtil")
isValid = oValidator.validate([ \
["txtField1", ["NonEmptyValidator"],"Please enter textField1"], \
["txtSSN", ["LengthValidator", 4],"Please enter 4 digit ssn"], \
["txtSSN", ["NumberValidator"],"Please enter a numeric value"]
)
Predefined validators (functions) can be called by their string name using call(...) method.
Since we have all the necessary things are worked out, heres a complete listing of ValidationUtils class. You are free to use and modify this class as per your requirements. Just let me know if your are using it. At least i'll know it was useful to someone.
-----------------------------------------------------
-- This class manages all the validation stuff --
-- @author : Raghavendra Kotikalapudi --
-- @email : ragha.unique2000@gmail.com --
-----------------------------------------------------

--Currently works only for text fields..
--Checks for validation on the given validator..
on isValidOnValidator me, memberName, lstValidatorAndParams

val = sprite(memberName).text
--Extract validator name..
validator = lstValidatorAndParams[1]
otherParams = lstValidatorAndParams
--Remove validator name...it now has params only.
otherParams.deleteAt(1)
--Achieves dynamic function calling..
return call(symbol(validator), me, val, otherParams)

end

--This is the main function to be called.
on validate me, lstMembersAndValidators

ret = true
repeat with lst in lstMembersAndValidators

if isValidOnValidator(me, lst[1], lst[2]) = false then
alert(lst[3])
ret = false
exit repeat
end if

end repeat

return ret

end


--Validates non emptiness..
on NonEmptyValidator me, str, lstOptionalParams

if voidP(str) then
return false
else if length(str) = 0 then
return false
else
return true
end if

end

--Validates of length of str in in the range (low, hi) inclusive
--lstOptParams has low, high pair
on LengthRangeValidator me, str, lstOptionalParams

len = length(str)
if len >= lstOptionalParams[1] and len <= lstOptionalParams[2] then return true else return false end if end --Validates for non existence of special symbols.. --i.e, str can contain a-z, A-Z or 0-9 on NoSpecialSymbolsValidator me, str, lstOptionalParams foundCount = PRegEx_Search([str], "~+|`+|!+|@+|#+|\$+|%+|\^+|&+|\*+|\(+|\)+|\{+|\}+|\[+|\]+|\++|\\+|\|+|:+|;+|/+|\<+|\>+|\?+|,+")

--If special char is found, validate to false
if foundCount > 0 then
return false
else
return true
end if

end

--Validates if the given str is a valid name or not, i.e., it should not contain
--special symbols or 0-9
on NameValidator me, str, lstOptionalParams

val = NoSpecialSymbolsValidator(me, str, lstOptionalParams)
if val = false then
return false
else
foundCount = PRegEx_Search([str], "[0-9]+")
--If number if found..
if foundCount > 0 then
return false
else
return true
end if
end if

end
New Validators can be added as an when needed. PRegEX_search(...) comes from PRegEx Xtra. Fortunately, it is free to download. This framework handles error notifications by showing alert messages whenever validation fails. Neat isn't it.

If you have any suggestions or improvements, please let me know through comments. Hope you find this useful!

Friday, July 2, 2010

Women and Their Craze for Possessions

A woman parked her brand-new Lexus in front of her office ready to show it off to her colleagues. As she got out, a truck passed too close and completely tore off the door on the driver's side. The woman immediately grabbed her cell phone, dialed 911, and within minutes a policeman pulled up. Before the officer had a chance to ask any questions, the woman started screaming hysterically.

Her Lexus, which she had just picked up the day before, was now completely ruined and would never be the same, no matter what the body shop did to it. When the woman finally wound down from her ranting and raving, the officer shook his head in disgust and disbelief. "I can't believe how materialistic you women are," he said. "You are so focused on your possessions that you don't notice anything else."

"How can you say such a thing?" asked the woman.

The cop replied, "Don't you know that your right arm is missing from the elbow down? It must have been torn off when the truck hit you."

"OH MY GOD!" screamed the woman. "Where's my new bracelet !!!"

Monday, June 7, 2010

Report generation in adobe director..

Report generation is perhaps the most plagued problem with director. There are a lot of xtras out there, but are commercial. Most of them are around $100-350, and all are limited in one way or another. After weeks of exploration, few of which included:
  1. Using adobe reader
  2. Interfacing it via. java program (this one almost worked)
  3. Wasted time with lots of useless xtras
I decided to make my own scheme, one which works in most situations. The idea is as follows:
  1. Create a HTML template of your report. For instance, if you wanted customer information report. You create a HTML template, fill in all the blanks with $1, $2, ... $n.
  2. From director, while generating the report, you first read in the template (preferably from root folder\templates\).
  3. Replace $1, $2, with appropriate values.
  4. Generate HTML file and open it with default browser.
I created a utility class for the above tasks. You'll be needing FileIO xtra and FileXtra4 (both of which are available for free)

-------------------------------------------------------------
--------------Report generation Utility class----------------
-------------------------------------------------------------

--Finds and replaces the first occurrence of 'aLookForString' with 'aReplaceString'
--in 'aString' and returns the new string
on findAndReplace me, aString, aLookForString, aReplaceString

n = aLookForString.length -1
is_ok = false

repeat while is_ok = false

place = offset(aLookForString, aString)

if (place = 0) then
is_ok = true
exit repeat
else
put aReplaceString into char place to (place+n) of aString
exit repeat
end if

end repeat

return aString
end

--Saves the text in given filename
on saveText me, text, filename

-- create the FileIO instance
fileObj = new(xtra "FileIO")

-- delete existing file, if any
openFile (fileObj,filename,2)
delete(fileObj)

-- create and open the file
createFile(fileObj,filename)
openFile(fileObj,filename,2)

-- check to see if file opened ok
if status(fileObj) <> 0 then
err = error(fileObj,status(fileObj))
alert "Error:"&&err
return FALSE
end if

-- write the file
writeString(fileObj,text)

-- close the file
closeFile(fileObj)

return TRUE

end

--Reads the text from a given filename
on readFromFile me, filename

-- create the FileIO instance
fileObj = new(xtra "FileIO")

-- open the file
openFile(fileObj,filename,1)

-- check to see if file opened ok
if status(fileObj) <> 0 then
err = error(fileObj,status(fileObj))
alert "Error:"&&err
return ""
end if

-- read the file
text = readFile(fileObj)

-- close the file
closeFile(fileObj)

--return the text
return text

end


Sample usage is illustrated below:

oUtilClass = new(script "UtilClass")

--Read html from the template
html = oUtilClass.readFromFile(the moviepath & "\\Templates\\summary report.htm")

--Fill in data..
global strSelectedDate
html = oUtilClass.findAndReplace(html, "$1", someVar)
html = oUtilClass.findAndReplace(html, "$2", anotherVar)

filename = the moviepath & "print.html"
oUtilClass.saveText(html, filename)

--Invoke through a browser..
fileXtra4Obj = xtra("FileXtra4").new()
fileXtra4Obj.fx_FileRunApp(the moviepath & "run.bat")



In run.bat, you just have to call print.html by writing "print.html", Duh!
Therefore, run.bat opens print.html with the default browser, which can then be printed, previewed by the courtesy of browser. Whats more, you also get to fiddle with niche layout settings at runtime. In other operating systems like linux, you just have to replace run.bat with a shell script.

Some Minor Tidbits

What if you wanted to generate a table at runtime? Here's what I'd do:

Generate HTML template from dreamweaver or MS word with one row of data in the table..
For example...
<html>
Some blah blah..

Name: $1 </br>
Age : $2 </br>

<table>
<tr>
<td> Subject </td>
<td> Marks </td>
</tr>

<tr>
<td> Some subject </td>
<td> 85 </td>
</tr>
</table>

</html>

Now, create a file template1_rows.txt containing the row data..<html>
<tr>
<td> $1 </td>
<td> $2 </td>
</tr>
Here's the big idea. Whenever you build a table, read in the row data template, fill it and append it to the main html. Here's an example. Highlighted code achieves dynamic table generation behavior.
 --Read html from the template
html = oUtilClass.readFromFile(the moviepath & "\\Templates\\template1.htm")

--Fill in data..
global strSelectedDate
html = oUtilClass.findAndReplace(html, "$1", name)
html = oUtilClass.findAndReplace(html, "$2", age)

tableRows = ""
--Read in the row template..
rowTemplate = oUtilClass.readFromFile(the moviepath & "\\Templates\\template1_rows.htm")

--Generate table rows..
repeat with row=1 to numRows
tableRow = rowTemplate
tableRow = oUtilClass.findAndReplace(tableRow , "$1", subject)

--Append data to tableRows..
tableRows = tableRows & rowTemplate
end repeat

--Fill in table data..
html = oUtilClass.findAndReplace(html, "$3", tableRows)

filename = the moviepath & "print.html"
oUtilClass.saveText(html, filename)

fileXtra4Obj = xtra("FileXtra4").new()
fileXtra4Obj.fx_FileRunApp(the moviepath & "run.bat")
I know, it looks complicated. But atleast this is transparent and you exactly know whats going on. Moreover, this approach gives you unlimited formatting options, works and is free. Once you get a hand of it, it'll seem pretty simple.

Controlling print behavior

If you don't want your table to break across pages, you can use . Beware, this only works with opera browser. So be sure to ship your software with opera. Even better, use opera portable (requires no installation), make appropriate changes to run.bat to invoke html with the shipped browser.

Comments and suggestions are welcome. If anyone has simpler and free approach, please let me know by posting comments.

Tuesday, June 1, 2010

Segmentation fault with c++ vector

Ever been in a situation where you got a seg. fault when you tried to push_back a pointer into the vector? What's more, you have a useless log file with no clues whatsoever. I had the same issue when i was working on an assignment with deadline in 2 hours. After whacking my head for 1-2 hours, I finally found a way to resolve the issue.

I was working on "simple ecosystem" project. The code where new fishes are created and added to the ecosystem seg. faulted. Take a look, I cut down unnecessary things to keep this example simple.
for (vector::iterator it = vecPossiblePositions.begin(); it!=vecPossiblePositions.end(); ++it)
{
//create a new fish..
Fish *f = new Fish();
f->setPosition(it->getX(), it->getY());

//This method does a push_back
//operation on some vector
ecosystem->addEcosystemObject(f);
}
If i comment out ecosystem->addEcosystemObject(f) line, then it runs without seg. fault. Apparently, the line Fish *f = new Fish() was causing the problem. So here's what i did.
Fish *f = NULL;
for (vector::iterator it = vecPossiblePositions.begin(); it!=vecPossiblePositions.end(); ++it)
{
//create a new fish..
f = new Fish();
f->setPosition(it->getX(), it->getY());

//This method does a push_back
//operation on some vector
ecosystem->addEcosystemObject(f);
}
and that fixed the problem! I have no idea why it worked. So, today's lesson of the day is "Keep the damn ptr declarations outside loops"

Enter teeki chawal

Got bored of same old food? Try this recipe..I found out about it from a friend of mine and made a few modifications of my own.

Here's what you need:
  1. Cooked rice
  2. Oil (obviously)
  3. Mirchi powder, jeera, salt, chopped onions, semi boiled and cut potato (one will do)
  4. Crushed tomatoes, c, carrots, beans, green peas, corn
Here's how you proceed:
  1. Heat a pan with lots of oil..
  2. Put jeera (one handful, needs to be more)
  3. Put onions and fry em' all at med flame
  4. Once onions are semi fried, put capsicum, potatoes and cook for like 7 mins
  5. Put remaining veggies and cook for another 7 mins.
  6. Add mirchi powder, and any other spices you fancy (Dhaniya powder, Hing, Garam masala will also do)
  7. Let it cook for another 5 mins..(At any point, if you notice that the veggies are burning, add a little bit of crushed tomato puree)
  8. Add 40% of the crushed tomatoes from the can.
  9. Cook for 10 mins.
  10. Now, taste the mixture, it should be slightly spicier, if not, add more spices. Also, at this point you should notice oil separating from the mixture
  11. Add cooked rice (cold one preferably), and stir for 3-5 mins..
That's it..enjoy your meal :)