Sunday, September 30, 2012

Two ways to find the max of 5 numbers


It started as an experiment to find out which of the two ways (I could think of) how to find the max of 5 numbers. I wanted to make this language agnostic, in other words, no library functions or language specific features.

I used Java for this. Here is the program:

//LargestIn5.java
//Accept 5 numbers and find the largest of the 5 numbers

import java.util.Scanner;

public class LargestIn5
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);

int a, b, c, d, e; // The five numbers
int nCount = 0;

System.out.print("Enter the first number: ");
a = input.nextInt();

System.out.print("Enter the second number: ");
b = input.nextInt();

System.out.print("Enter the third number: ");
c = input.nextInt();

System.out.print("Enter the fourth number: ");
d = input.nextInt();

System.out.print("Enter the fifth number: ");
e = input.nextInt();

if ((a > b) && (a > c) && (a > d) && (a > e))
{
System.out.println(a + " is the largest");
System.out.println("nCount = 4");
}
else if ((b > a) && (b > c) && (b > d) && (b > e))
{
System.out.println(b + " is the largest");
System.out.println("nCount = 4");
}
else if ((c > a) && (c > b) && (c > d) && (c > e))
{
System.out.println(c + " is the largest");
System.out.println("nCount = 4");
}
else if ((d > a) && (d > b) && (d > c) && (d > e))
{
System.out.println(d + " is the largest");
System.out.println("nCount = 4");
}
else if ((e > a) && (e > b) && (e > c) && (e > d))
{
System.out.println(e + " is the largest");
System.out.println("nCount = 4");
}
else
{
System.out.println("There is something wrong...");
System.out.println("nCount = 0");
}

if (a > b)
{
nCount++;
if (a > c)
{ //a > b & c
nCount++;
if (a > d)
{ // a > b & c & d
nCount++;
if (a > e)
{ // a > b & c & d & e
nCount++;
System.out.println(a + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > a > b & c & d
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > a > b & c
nCount++;
if (d > e)
{ // d > e & a > b & c
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > a > b & c
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
else
{ // c > a > b
nCount++;
if (c > d)
{ // c > d & a > b
nCount++;
if (c > e)
{ // c > d & e & a > b
nCount++;
System.out.println(c + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > c > d & a > b
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > c > a > b
nCount++;
if (d > e)
{ // d > e & c > a > b
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > c > a > b
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
}
else
{ // b > a
nCount++;
if (b > c)
{ // b > a & c
nCount++;
if (b > d)
{ // b > a & c & d
nCount++;
if (b > e)
{ // b > a & c & d & e
nCount++;
System.out.println(b + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > b > a & c & d
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > b > c
nCount++;
if (d > a)
{ // d > a & b > c
nCount++;
if (d > e)
{ // d > e & a & b > c
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > a & b > c
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // a > d > b > c
nCount++;
if (a > e)
{ // a > e & d > b > c
nCount++;
System.out.println(a + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > a > d > b > c
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
}
else
{ // c > b > a
nCount++;
if (c > d)
{ // c > d & b > a
nCount++;
if (c > e)
{
nCount++;
System.out.println(c + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
else
{ // d > c > b > a
nCount++;
if (d > e)
{ // d > e & c > b > a
nCount++;
System.out.println(d + " is the largest");
System.out.println("nCount = " + nCount);
}
else
{ // e > d > c > b > a
nCount++;
System.out.println(e + " is the largest");
System.out.println("nCount = " + nCount);
}
}
}
}
}
}


The variable nCount was to find out how many conditions are being executed. Method 2 seems more complex. But is it better in terms of number of conditions executed to find the answer.

Output from few runs:

$ java LargestIn5
Enter the first number: 1
Enter the second number: 2
Enter the third number: 3
Enter the fourth number: 4
Enter the fifth number: 5
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 2
Enter the second number: 3
Enter the third number: 4
Enter the fourth number: 5
Enter the fifth number: 1
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 3
Enter the second number: 4
Enter the third number: 5
Enter the fourth number: 1
Enter the fifth number: 2
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 4
Enter the second number: 5
Enter the third number: 1
Enter the fourth number: 2
Enter the fifth number: 3
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 
$ java LargestIn5
Enter the first number: 5
Enter the second number: 1
Enter the third number: 2
Enter the fourth number: 3
Enter the fifth number: 4
5 is the largest
nCount = 4 
5 is the largest
nCount = 4 


Sometimes, the more complex looking code is not necessarily the more optimal one.

Saturday, March 31, 2012

Handling Return Values

Recently, I was discussing Defensive Programming with a relative newcomer to the industry. I mentioned that the concept was not dependent on languages and more logical in nature. In other words, though a language does not have specific language facilities for Defensive Programming.

To give an example, I used the following:

Consider a function is_data_found() which returns one of the following values:

#define SUCCESS 0
#define FAILURE 1
#define NO_DATA_FOUND 2

int fun1()
{
    //search for data in DB
    //If data not found return NO_DATA_FOUND
    //else if operation failed, then return FAILURE
    //Return SUCCESS
}

Now, one of the common (wrong) ways for a caller fun2() to handle the return values from the call to fun1() is:

void fun2()
{
    //Call fun1
    //if return value is not SUCCESS, continue process
    //else, throw exception
}

Based on code review feedback or testing, they might realize that NO_DATA_FOUND might be a valid scenario. In other words, fun2() might need to do create_if_not_found operation.

To accommodate this, they might change the caller to:

void fun3()
{
    //Call fun1
    //if return value is NO_DATA_FOUND, then create row
    //else if return value is SUCCESS, then continue process
    //else, throw exception
}

This would be fine in the current scenario. But what if a new return value is added to fun1(), say WARNING_POTENTIAL_STALE_DATA:

#define SUCCESS 0
#define FAILURE 1
#define NO_DATA_FOUND 2
#define WARNING_POTENTIAL_STALE_DATA 3

int fun1()
{
    //search for data in DB
    //If data not found return NO_DATA_FOUND
    //else if operation failed but previously fetched data available, then return WARNING_POTENTIAL_STALE_DATA
    //else if operation failed and no previously fetched data available, then return FAILURE
    //Return SUCCESS
}

Now, fun2() would not provide the complete functionality since it does not know about the new functionality. However, no one would notice this, since fun2() does not have the right code for handling such scenarios.

A better way to write the caller is:

void fun4()
{
    //Call fun1
    //if return value is NO_DATA_FOUND, then create row
    //else if return value is SUCCESS, then continue process
    //else if return value is FAILURE, then throw DATA_FETCH_FAILED_EXCEPTION
    //else, return UNKNOWN_RETURN_VALUE_EXCEPTION
}

Now, fun4() will throw an exception when WARNING_POTENTIAL_STALE_DATA is thrown.

Cheers!
Karthick S.

Sunday, December 25, 2011

Installing rvm in mac os x lion using bash

They are giving MacBook Pro as our laptop in our office. I wanted to install ruby. For this purpose, I wanted to install rvm. Based on instructions I found in the rvm site, I gave the command to download the installer and do the installation:

$ bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
-sh: syntax error near unexpected token `<'

Since this can be split into two commands, I did the same:

$ curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer > rvm-installer
$ bash rvm-installer

When I did this, it threw out a lot of output. Hidden in this output was a line:

Installation of RVM to /Users/[user_name]/.rvm/ is complete.

Once I saw this, I did not bother looking further to see if things have failed or if there are any warnings. Turns out it did not work fine. There was an error in the output:

is_a_function: command not found

When I went ahead and added this path in .bash_profile, the error surfaced again. Google did not help either. Finally, with the help of an answer for my question at StackOverflow, I cracked it:
$ curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer | bash -s stable
Now to figure out how to install ruby. :)

Cheers!
Karthick S.

Saturday, October 22, 2011

Special options while printing in Python 3.x

One more post about printing values in Python 3.x and how it differs with Python 2.x.

To print the end of line using Python 2.x, all you need to do is add a comma to the end of the print list.

print "Hello ",
print "World"

The statements above print "Hello World" on the screen.

But with Python 3.x, it is different

print ("Hello ", end='')
print ("World")

This prints "Hello World" on the screen.

Another way to print the same would be:

print ("Hello", end=" ")
print ("World")

In other words, whatever is sent as a value for end is appended to the end of whatever is printed. You can even specify multi-character strings as the value for end.

In addition to this, there is another argument sep, which specifies the separator between the items to be printed.

print ("Hello", "World", sep = " ")

This would help in creating output as a CSV or a TSV files for example:

print ("FirstName", "LastName", sep=",")

Cheers!
Karthick S.

Tuesday, October 18, 2011

Differences in print between Python 2.x and Python 3.x

Recently, I started learning Python and installed the latest version available online - Python 3.2. I did this in spite of the fact that the book I was using Practical Programming: An Introduction to Computer Science using Python.

After completing a few exercises using the Python command line, I decided to save my script and execute them from command line. That is when things started to fail. Python would not allow me to print the output. It kept showing the variable to be printed and said SyntaxError: invalid syntax. To illustrate in command line, it was something like:

>>> i=5
>>> print i
File "", line 1
print i
^
SyntaxError: invalid syntax

Google could not help me with this. Finally, I went with intuition and solved it. I needed to enclose the arguments to print using parenthesis. But the book did not mention it.

This is because the enclosing parenthesis was not a requirement in Python 2.x, but is required in Python 3.x.

It kind of pissed me off (and I am sure I am not the first Python newbie to feel this way), that the language designers did not give a reasonably clear error message for this one.

Cheers!
Karthick S.

Wednesday, December 08, 2010

Moving from rspec 2.0.0.beta.18 to rspec 2.0.0.beta.22

This post is primarily for anyone who is using rspec 2.0.0.beta.18 as specified in the Ruby on Rails Tutorial and find that they hit upon the following problem:

Failure/Error: Unable to find C to read failed line
undefined method `get' for # do
include RSpec::Rails::RequestExampleGroup

Whenever they run the tests:
$ rspec spec/requests/layout_links_spec.rb
To fix this, I installed rspec 2.0.0.beta.22 by using the command:
$ gem install rspec -v 2.0.0.beta.22 --pre
Then I changed the version of rspec specified in my Gemfile as:
$ git diff Gemfile
WARNING: terminal is not fully functional
diff --git a/Gemfile b/Gemfile
index 28af226..865b9de 100644
--- a/Gemfile
+++ b/Gemfile
@@ -30,10 +30,11 @@ gem 'sqlite3-ruby', :require => 'sqlite3'
# end

group :development do
- gem 'rspec-rails', '2.0.0.beta.18'
+ gem 'rspec-rails', '2.0.0.beta.22'
end

group :test do
- gem 'rspec', '2.0.0.beta.18'
+ gem 'rspec', '2.0.0.beta.22'
end

warning: LF will be replaced by CRLF in Gemfile.
The file will have its original line endings in your working directory.
Then I installed this version of rspec using the command:
$ bundle install

Now I got a new error:
1) LayoutLinks should have a Home page at '/'
Failure/Error: response.should have_selector('title', :content => "Home")
undefined method `has_selector?' for #
# ./spec/requests/layout_links_spec.rb:6:in `block (2 levels) in '
Google suggested the solution in this page: Add "webrat" the Gemfile, do a bundle install and that should do it.

In my case, I had to uncomment the entry in the Gemfile.
$ git diff Gemfile
WARNING: terminal is not fully functional
diff --git a/Gemfile b/Gemfile
index 28af226..ea7d729 100644
--- a/Gemfile
+++ b/Gemfile
@@ -25,15 +25,16 @@ gem 'sqlite3-ruby', :require => 'sqlite3'
# Bundle gems for the local environment. Make sure to
# put test-only gems in this group so their generators
# and rake tasks are available in development mode:
-# group :development, :test do
-# gem 'webrat'
-# end
+group :development, :test do
+ gem 'webrat'
+end

group :development do
- gem 'rspec-rails', '2.0.0.beta.18'
+ gem 'rspec-rails', '2.0.0.beta.22'
+# gem 'annotate-models', '1.0.4'
end

group :test do
- gem 'rspec', '2.0.0.beta.18'
+ gem 'rspec', '2.0.0.beta.22'
end

warning: LF will be replaced by CRLF in Gemfile.
The file will have its original line endings in your working directory.
That fixed it!

Cheers!
Karthick S.

Thursday, July 15, 2010

WAMPServer and Apache on Windows: Changing the port number

It all started when I wanted to create an application with MySQL as a backend. Since I am not well versed in MySQL, one of my colleagues suggested that I use phpmyadmin. He had a nice installation of phpmyadmin installed in the tools development server we have in our office and I tried it for sometime. Today morning, I decided to install phpmyadmin in my local machine so that I can work on my application when at home too. But there was no one around who had installed phpmyadmin in Windows. :(

After a few iterations in trying to get PHP, Apache and MySQL to talk to each other in Windows, I realized that I was going nowhere and hence decided to install one of the WAMP applications that are lying around online. I chose WampServer.

After installing WampServer, I noticed that it comes with phpmyadmin pre-installed. :)

Now this is the problem I faced. The default port for Apache as configured in the installation in WAMPServer was 80 and this was already being used by Skype. The following are the steps which I followed to change this port:
1) Left click on the WAMPServer tray icon and choose "Apache".
2) Open "httpd.conf".
3) In the file, search for "Listen 80". The "80" is the current port number.
4) Change it to whichever port number you want it to be. Choose a port that is not already in use.
5) "Restart All Services" by left-clicking on the tray icon again.
I got most of this information from this page.

This brought about another irritating albeit minor problem: If you notice in the image above, there are shortcuts to "Localhost" and "phpmyadmin" in this menu. These still use the port "80". Every time I click on these shortcuts, I get a page not found and then need to change the port.

How do I fix that one? I tried the steps in the page linked above, but that information seemed to be for some other version of WAMPServer.

So, here are the steps I found for WAMPServer Version 2.0:
1) Go to the folder in which you have installed WAMPServer (X:\Wamp, by default).
2) You should see a file "wampmanager.tpl" in this folder. Open it.
3) Search for "http://localhost/phpmyadmin/" and change it to "http://localhost:[YOURPORTNUM]/phpmyadmin/".
4) Save and close this file.
5) Restart WAMPServer.

That should fix it!

Cheers!
Karthick

Saturday, June 12, 2010

RoR page does not load on the browser

Hi, As usual, I tried to learn something of something new - Ruby on Rails. When I tried to create a brand new application as suggested in "Beginning Ruby on Rails", I hit upon a road block. The application would not load. And the log file said:
- Could not open library 'libsqlite3': The specified module could not be found.

- Could not open library 'libsqlite3.dll': The specified module could not be found.

- Could not open library 'sqlite3': The specified module could not be found.

- Could not open library 'sqlite3.dll': The specified module could not be found.
And lots of other things which I could just not understand.

After searching for a long time and taking help from our local ruby-on-rails expert (who had never done this in Windows), I found that this is a rare occurrence. Finally, when we found out the root cause, it was pretty simple. All I needed to do was to put sqlite3.exe and sqlite3.dll in my path.

Cheers!
Karthick S.

Saturday, March 01, 2008

Tips for unix sort command

You might have used the sort command many times in the past for simple sort requirements.

But did you know that one of the most frustrating and tough to find out problems in sort command is that the option -n has been missed. This option is used to specify that the sorting has to be done numerically - in other words, the field that is being used for sorting will be considered to be a numeric field.

Another commonly used option of sort is -k. This option is used to specify the field based on which the sorting needs to be done. For example,

Recently, I used sort for one of my scripts and was irritated that I did not know the way to do nested sort (sort first by key1 and then by key2...). What was more irritating was that even the life saving man page did not indicate any option for this.

After some searching in the net, I found some reference to the -k option being allowed more than once for the same sort command. And that saved my day:
sort -k1,1 -k3,3 filename

sorts the fields in filename first by field 1 (because of 1,1) and in case of conflicts between those fields, by field 3 (3,3) and redirects the output to stdout.

This can be combined with the -n option to sort numerically - considering that the field is numeric. For example,

sort -k1,1n -k3,3 filename

The above command sorts the first field numerically and the second field in consideration (actually the third field in the file) alphabetically and redirects the output to stdout.

There is a caveat though. The following command is different from the one above:

sort -n -k1,1 -k3,3 filename

considers that all the fields that need to be sorted will be sorted numerically. In other words, the sorting will happen on field 1 numerically and then on field 3 numerically.

Rgds,
Karthick S.

Tuesday, November 08, 2005

Bash - Choking the system - Fork bomb

This is a wicked post. If you execute the script given in this, then you would need to restart the machine. The command:
:(){ :|:& };:

What does this mean:
:()
{
: | : &
}
:


It creates a function called : and then calls the same recursively in the background. This would cause the system to choke due to continues creation of processes. This is called as a fork-bomb. Fork-bombs can be created in many languages/ways. Check the following page: http://en.wikipedia.org/wiki/Fork_bomb

Hope this helps.

Rgds,
Karthick S.