Thursday, January 30, 2020

Bulb and Switch Puzzle

Statement: There is one bulb in a room with its door closed. There are 3 switches (A,B,C) outside. You can open the door only once. You have to figure out which switch belongs to the bulb.


Solution:
1) Turn on the first switch and keep it on for a few minutes.

2) Switch off the first switch and turn on second switch.

3) Immediately enter the room
      a) If bulb is on, second switch it is.
      b) If bulb is off and warm, then first switch.
      c) If bulb is off and cold, then third switch.

Saturday, December 21, 2019

Basic Unix commands of Frequent use


Following are some commands which you will use very often->

Suppose you are not able to deploy your ear successfully ,or your application is running very slowly; then most definitely you are short on space.

1) Use the following 2 commands to see the available space and memory->
$ df -h (Space)
$ free -m (Memory)

2) Check "class file" exists in which jar file.
$ find -name "*.jar" | xargs grep CitiNotesDataUtility.class

3) Find all instances of the specified process currently running.
$ ps -ef | grep processName
$ ps -ef | grep processName | grep java (java processes)

4) Kill Process : kill
$ kill -9 processId

5) List Directory Contents : ls
$ ls -a

6) Display Manual pages : man <command>
Linux has as extensive set of online documentation. They are referred to as manual pages.
$ man ls

7) Concatenate files: cat
$ cat file1 file2 > newFile

8) Current working directory
$ pwd

9) List all the current running processes
$ ps

10) Change Directory
$ cd /usr/bin
$ cd.. (go back)

11) Make Directory : mkdir
$ mkdir newDirName

12) Remove files and directories: rm
$ rm file.txt

$ rm dirName


Anti-Patterns in Software Development

Anti-patterns are certain patterns in software development that are considered bad programming practices.

Anti-patterns are the opposite of design patterns and are undesirable.

Some Anti-Patterns:

1) Bleeding Edge : Use cutting-edge(latest) technologies that are still untested or unstable leading
to cost overruns, under-performance or delayed delivery.

2) Cash Cow : A profitable legacy product that often leads to complacency about new products.

3) Micromanagement : Many times a team is rendered ineffective due to excessive observation,
supervision and hands-on involvement (lack of trust).

4) Mushroom management : Keeping employees in the dark and feed manure.

5) Seagull management : Management in which managers only interact with employees when a problem arises - they fly in, make a lot of noise, dump on everyone, do not solve the problem,
then fly out.

6) Smoke and Mirrors : Demonstrating unimplemented functions as if they were already implemented.

7) Brooks Law : Adding more resources to a project to increase velocity, when the project is already
slowed down by co-ordination overhead.

8) Big ball of mud: A system with no recognizable structure.

9) Interface bloat: Making an interface so powerful that it is extremely difficult to implement.

10) Database-as-IPC: Using a database as the message queue for routine inter-process communication where a much more lightweight mechanism would be suitable.

11) Circular dependency: Introducing unnecessary direct or indirect mutual dependencies between objects or software modules.

12) God object: Concentrating too many functions in a single part of the design (class).

13) Busy waiting: Consuming CPU while waiting for something to happen, usually by repeated checking instead of messaging.

14) Caching failure: Forgetting to clear a cache that holds a negative result (error) after the error condition has been corrected.

15) Cargo cult programming: Using patterns and methods without understanding why.

16) Hard code: Embedding assumptions about the environment of a system in its implementation.

17) Lava flow: Retaining undesirable (redundant or low-quality) code because removing it is too expensive or has unpredictable consequences.

18) Repeating yourself: Writing code which contains repetitive patterns and sub-strings (duplicate code); avoid with once and only once (abstraction principle)

19) Spaghetti code: Programs whose structure is barely understandable, especially because of
misuse of code structures.

20) Copy and paste programming: Copying (and modifying) existing code rather than creating generic solutions.

21) JAR hell: Over-utilization of multiple JAR files, usually causing versioning and location
problems because of misunderstanding of the Java class loading model.

Thursday, March 9, 2017

Erase everything - Database schema

If you wish to format your schema, then follow these steps->

1) Run the following query->

SELECT 'DROP '||object_type||' '|| object_name||  DECODE(object_type,'TABLE',' CASCADE CONSTRAINTS;',';') FROM user_objects ORDER BY object_id DESC;

2) Copy and paste the output from above query and execute it.

3) Execute this -> PURGE RECYCLEBIN;

Tuesday, December 27, 2016

Count no of String occurences in single pass

package com.prac;

import java.util.*;

public class CountStringOccurences 
{
public static void main(String[] args) {

String[] str = {"A","B","C","A","A","B","B","B","B","B","C","A","D","E","E","F","D","D"};

Map<String, Integer> hm = new HashMap<String, Integer>();

int cnt=1;

for(String ans : str)
{
if(hm.containsKey(ans))  //check if the key is already present
{
 cnt=hm.get(ans); // if present then fetch its count and increment it
 cnt++;
}
else
{
   cnt=1; //else set count to 1
}

     hm.put(ans, cnt);  // add the data in map
}


System.out.println("hm="+hm);
}
}


Output:
hm={D=3, E=2, F=1, A=4, B=6, C=2}

Thursday, December 15, 2016

Find first non-repeating character in String

Following code finds the first non-repeating character in just one pass :)


public class NonRepeating{

public static char firstNonRepeatingChar(String word)
{
Set<Character> repeating = new HashSet<Character>();
List<Character> nonRepeating = new ArrayList<Character>();

for (int i = 0; i < word.length(); i++)
{
char letter = word.charAt(i);
if (repeating.contains(letter))
{
continue;
}

if (nonRepeating.contains(letter))
{
nonRepeating.remove((Character) letter);
        repeating.add(letter);
}
else
{
nonRepeating.add(letter);
}
}

if(nonRepeating.size()!=0)
 return nonRepeating.get(0);
else
  return '\0';
}


public static void main(String[] args)
{
char ans = firstNonRepeatingChar("hrishikesh");

System.out.println("ans="+ans);
}
}

Wednesday, December 14, 2016

Fibonacci Series

Fibonacci Series = 0 1 1 2 3 5 8 13 21 34.

Basically we have to add the previous and current number to get the next number.


Java Code->
public class Fibonacci
{
    static int[] fibonacci(int n)
    {
     //Declare an array to store Fibonacci numbers
     int f[] = new int[n+1];
     int i;
   
     //0th and 1st number of the series are 0 and 1
     f[0] = 0;
     f[1] = 1;
   
     for (i = 2; i <= n; i++)
     {
    //Add the previous 2 numbers in the series and store it
        f[i] = f[i-1] + f[i-2];
     }
   
      return f; //Return the array back to main method.
    }

 
   public static void main(String[] args)
   {
     int n = 9;
     int[] ans = fibonacci(n);
 
     for (int i = 0; i <= n; i++)
     {
        System.out.print(ans[i]+" "); //Print the array.
     }
   }

}

Friday, December 9, 2016

Pair Programming

In Pair Programming two programmers work together on the same computer.

One person writes the code while the other reviews it. They also switch their roles frequently.

Both have to maintain a running commentary, basically they have to "program out loud".


Multiple configuration files

Hibernate is designed to be used with a large set of databases. The details of those databases are configured in an XML file called hibernate.cfg.xml.

If we wish to use multiple databases in our application then we have to maintain separate configuration files.


Example: Application uses Oracle and Derby database.

Here we have to maintain 2 configuration files, lets say we name it oracleconfig.cfg.xml and derbyconfig.cfg.xml.

To access them we need to create separate session Factories ->

1) SessionFactory sessionFactory1 = new  Configuration().configure("oracleconfig.cfg.xml").buildSessionFactory();

2) SessionFactory sessionFactory2 = new Configuration().configure("derbyconfig.cfg.xml").buildSessionFactory();

Thursday, December 8, 2016

Space Complexity

Usually the term Space Complexity is misused for Auxiliary Space.

Following are the correct definitions of Auxiliary Space and Space Complexity.

Auxiliary Space is the temporary space used by an algorithm.

Space Complexity of an algorithm is total space taken by the algorithm with respect to the input size.

Space complexity includes both Auxiliary space and space used by input.

Example:
While comparing sorting algorithms on the basis of space, Auxiliary Space would be a better choice than Space Complexity.


Wednesday, December 7, 2016

Analysis of Loops - Calculating Time Complexity

1) O(1): Time complexity of a function is considered as O(1) if it doesn’t contain loop, recursion and call to any other non-constant time function.

swap() function or loop or recursion that runs a constant number of timeshas O(1) time complexity.

Example:

for (int i = 1; i <= c; i++) {  // Here c is a constant   
        // some expressions
 }


2) O(n): Time Complexity of a loop is considered as O(n) if the loop variables is incremented / decremented by a constant amount.

Example:

for (int i = 1; i <= n; i += c) {   // Here c is a constant  
        // some expressions
}


3) O(n2: Time complexity of nested loops is equal to the number of times the innermost statement is executed. Selection sort and Insertion Sort have O(n2 time complexity.

Example:

for (int i = 1; i <=n; i += c) {
       for (int j = 1; j <=n; j += c) {
          // some expressions
       }
 }



4) O(Logn): Time Complexity of a loop is considered as O(Logn) if the loop variables is divided / multiplied by a constant amount. Binary Search has O(Logn) time complexity.

for (int i = 1; i <=n; i *= c) {
       // some expressions
}



5) O(LogLogn): Time Complexity of a loop is considered as O(LogLogn) if the loop variables is reduced / increased exponentially by a constant amount.
 
for (int i = 2; i <=n; i = pow(i, c)) {  // Here c is a constant greater than 1   
       // some O(1) expressions
}
 

How to combine time complexities of consecutive loops?
When there are consecutive loops, we calculate time complexity as sum of time complexities of individual loops.

for (int i = 1; i <=m; i += c) {  
        // some expressions
}

for (int i = 1; i <=n; i += c) {
        // some expressions
}

Time complexity of above code is O(m) + O(n) which is O(m+n)
If m == n, the time complexity becomes O(2n) which is O(n).  


How to calculate time complexity when there are many if, else statements inside loops?
Worst case time complexity is the most useful among best, average and worst. Therefore we need to consider worst case.

We evaluate the situation when values in if-else conditions cause maximum number of statements to be executed.

For example consider the linear search function where we consider the case when element is present at the end or not present at all.

When the code is too complex to consider all if-else cases, we can get an upper bound by ignoring if else and other complex control statements.

Asymptotic Notations - Theta , Big O and Omega

Asymptotic notations are mathematical tools to represent time complexity of algorithms for asymptotic analysis.

The following 3 asymptotic notations are mostly used to represent time complexity of algorithms.


1) Θ Notation: The theta notation bounds a functions from above and below, so it defines exact asymptotic behavior.

A simple way to get Theta notation of an expression is to drop low order terms and ignore leading constants.

Example:
3n3 + 6n2 + 6000 = Θ(n3)

Dropping lower order terms is always fine because there will always be a n0 after which Θ(n3) beats Θn2) irrespective of the constants involved.



2) Big O Notation: The Big O notation defines an upper bound of an algorithm, it bounds a function only from above.

Example: Consider the case of Insertion Sort.

It takes linear time in best case and quadratic time in worst case. We can safely say that the time complexity of Insertion sort is O(n^2).

If we use Θ notation to represent time complexity of Insertion sort, we have to use two statements for best and worst cases:
1. Worst case time complexity = Î˜(n^2).
2. Best case time complexity = Î˜(n).

The Big O notation is useful when we only have upper bound on time complexity of an algorithm. Many times we easily find an upper bound by simply looking at the algorithm.



3) Ω Notation: Just as Big O notation provides an asymptotic upper bound on a function, Ω notation provides an asymptotic lower bound.

Ω Notation can be useful when we have lower bound on time complexity of an algorithm.

The best case performance of an algorithm is generally not useful, the Omega notation is the least used notation among all three.

Example: Consider the case of Insertion Sort.

The time complexity of Insertion Sort can be written as Ω(n), but it is not a very useful information about insertion sort, as we are generally interested in worst case and sometimes in average case.

Tuesday, December 6, 2016

Worst, Average and Best Case in Algorithms

Lets take an example of Linear Search and analyze it using Asymptotic analysis.

We can have three cases to analyze an algorithm:
1) Worst Case
2) Average Case
3) Best Case


Worst Case Analysis (Usually Done)
In this, we calculate upper bound on running time of an algorithm. We must know the case that causes maximum number of operations to be executed. For Linear Search, the worst case happens when the element to be searched is not present in the array. When the element is not present, search() functions compares it with all the elements of array one by one.

Therefore, the worst case time complexity of linear search would be Θ(n).


Average Case Analysis (Sometimes done
In this, we take all possible inputs and calculate computing time for all of the inputs. Sum all the calculated values and divide the sum by total number of inputs. We must know (or predict) distribution of cases. For the linear search problem, let us assume that all cases are uniformly distributed (including the case of element not being present in the array).

So we sum all the cases and divide the sum by (n+1).


Best Case Analysis (Bogus
In this, we calculate lower bound on running time of an algorithm. We must know the case that causes minimum number of operations to be executed. In the linear search problem, the best case occurs when the element is present at the first location.

So time complexity in the best case would be Θ(1)

Analysis of Algorithms - Asymptotic Analysis

Algorithm: An algorithm is step by step instructions to solve a given problem.


Why performance analysis?
There are many important things that should be taken care of, like user friendliness, modularity, security, maintainability, etc. Why to worry about performance?

Evaluation of an algorithm is required to find the most optimized solution for solving a given problem.

For example:
While travelling from Place A to Place B one needs to select the best mode of transport (Flight, Train , Bus etc) based upon the budget and urgency.


Given two algorithms for a task, how to find which one is better?
One way is – implement both the algorithms and run the two programs on your computer for different inputs and see which one takes less time. There are many problems with this approach.
1) It might be possible that for some inputs, first algorithm performs better than the second  and vice versa.
2) Also for some inputs, first algorithm might perform better on one machine and the second works better on other machine for some other inputs.


Asymptotic Analysis is the big idea that handles above issues in analyzing algorithms. In Asymptotic Analysis, we evaluate the performance of an algorithm in terms of input size (we don’t measure the actual running time). We calculate, how does the time (or space) taken by an algorithm increase with the input size.

For example: Searching a given item in a sorted array. 
There are 2 ways - Linear and Binary search.

To understand how Asymptotic Analysis solves the above mentioned problems in analyzing algorithms, let us say we run the Linear Search on a fast computer and Binary Search on a slow computer. For small values of input array size, the fast computer may take less time. But, after certain value of input array size, the Binary Search will definitely start taking less time compared to the Linear Search even though the Binary Search is being run on a slow machine.

The reason is the order of growth of Binary Search is logarithmic while that of Linear Search is linear. So the machine dependent constants can always be ignored after certain values of input size.


Does Asymptotic Analysis always work?
Asymptotic Analysis is not perfect, but that’s the best way available for analyzing algorithms.

Sunday, December 4, 2016

Internal working of HashSet

Set is a collection that contains no duplicate elements. So, it can contain at most one null.
HashSet implements Set interface in java. It is not synchronized and is not thread safe.

Example: Showing HashSet does not allow duplicate elements.

public class Test {
   public static void main(String[] args) throws IOException {
        HashSet hashSet = new HashSet();
        hashSet.add(20);
        hashSet.add("Test");
        hashSet.add("XYZ");
        hashSet.add(20);
        hashSet.add("Test");
        System.out.println("Set = "+hashSet);
   }
}


Output:
Set = [20, Test, XYZ]


Internal Working:
Internally when the duplicate elements are passed to the HashSet, the add(e) method in HashSet returns false when the element exists, else it returns true.

When we have a look at the HashSet.java in java API, we can see the following code:

public class HashSet extends AbstractSet implements Set, Cloneable, java.io.Serializable
{
    private transient HashMap<E,Object> map; 

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    public HashSet() {
        map = new HashMap<>();
    }

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

    /**
    * Some code
    */
}

Set achieves the uniqueness in its elements through HashMap. In HashMap, each key is unique. So, when an object of HashSet is created, it will create an object of HashMap.

When an element is passed to Set, it is added as a key in the HashMap in the add(Element e) method. Now, a value needs to be associated to the key. Java uses a Dummy value (new Object) which is called PRESENT in HashSet.

In HashMap, the put(Key k,Value V) method returns null, if the key is unique and the key gets added to the map. It returns old value of the key, if the key is duplicated.

public V put(K key, V value) {
/* Some code */
}

In add(e) method, the return value of map.put(key,value) method is checked with null value.

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

If map.put(key,value) returns null, then map.put(e, PRESENT)==null will return true and element gets added to the HashSet.

If map.put(key,value) returns the old value of the key, then map.put(e, PRESENT)==null will return false and element wont be added to the HashSet.

remove() method also works in the same way.

public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}

As you know HashSet uses same values for all keys, it is really important to override equals() and hashCode() for any object you are going to store in HashSet thus making the object Immutable.

Thursday, November 17, 2016

Volatile in JAVA

Volatile keyword can be applied only to variables. It cannot be applied to class or method.

Volatile is used to indicate that a variable's value will be modified by different threads.

The value of volatile variable never get cached thread-locally; all reads and writes go straight to main memory.

A volatile variable can be used as an alternative way of to achieve synchronization in Java in some cases, like visibility. 

With volatile variable, it's guaranteed that all reader threads will see updated value of the volatile variable once write operation is completed, without volatile keyword different reader threads may see different values.

Example:
Imagine a situation in which two or more threads have access to a shared object which contains a counter variable declared like this:

public class SharedVariable {
    public int counter = 0;
}

Imagine too, that only Thread 1 increments the counter variable, but both Thread 1 and Thread 2 may read the counter variable from time to time.

If the counter variable is not declared volatile there is no guarantee about when the value of the counter variable is written from the CPU cache back to main memory. This means, that the counter variable value in the CPU cache may not be the same as in main memory.

The problem with threads not seeing the latest value of a variable because it has not yet been written back to main memory by another thread, is called visibility problem (updates of one thread are not visible to other threads).

By declaring the counter variable volatile all writes to the counter variable will be written back to main memory immediately. Also, all reads of the counter variable will be read directly from main memory. Here is how the volatile declaration of the counter variable looks:

public class SharedVariable {
    public volatile int counter = 0;
}

Declaring a variable volatile thus guarantees the visibility for other threads of writes to that variable.

Sunday, November 13, 2016

Difference between Sleep and Wait

sleep() is a method which is used to hold the process for some time but wait() method causes the thread to go in waiting state and it won’t come back automatically until notify() or notifyAll() is called.

The major difference is that wait() releases the lock while sleep() does not release any lock.

Wait is used for inter-thread communication while sleep is used to introduce pause on execution.

Thread.sleep() sends the current thread into the "Not Runnable" state for some amount of time. If another thread calls t.interrupt() it will wake up the sleeping thread. Note that sleep is a static method, which means that it always affects the current thread.
Even if we call t.sleep() where t is a different thread; even then, the current thread will sleep, not the t thread.

object.wait() sends the current thread into the "Not Runnable" state, like sleep(), but with a twist. Wait is called on an object, not a thread; we call this object the lock object. Before lock.wait() is called, the current thread must synchronize on the lock object; wait() then releases this lock, and adds the thread to the "wait list" associated with the lock. Later, another thread can synchronize on the same lock object and call lock.notify(). This wakes up the original, waiting thread.

Friday, November 11, 2016

Internal working of ArrayList

ArrayList is the most commonly used DataStructure in JAVA.

Internally it conatins an Array of Objects as follows ->
private transient Object[]elementData;

When we actually create an arrayList following piece of code is executed ->
this.elementData=new Object[initial capacity];



ArrayList can be created in two ways ->

1. List<String> myList=new ArrayList<String>(); 
(default constructor is invoked and internally creates an array of Object with default size 10)

2. List<String> myList=new ArrayList<String>(5);
(constructor with an integer argument is invoked and internally creates an array of Object with the size, specified in the constructor argument, which happens to be 5 in this case)



Unlike normal arrays, the size of the ArrayList grows dynamically.

Before adding element into the array it checks the current size of filled elements and the maximum size of the array. If the size of filled elements is greater than maximum size of the array then size of the array increases.

But since size of the array cannot be increased dynamically, internally a new Array is created with size 1.5 * currentSize and data from the old Array is copied into this new Array.

Wednesday, October 26, 2016

Why DDL is faster than DML?

DDL is always and always faster than DML.

After firing DDL statement we cannot fire rollback command, but in DML we can.

The reason being for DML; Oracle stores records in Redo Log Files; and copies them back during rollback.

For DDL statements; Log Files are not maintained.



One common question always asked is this -> What is the difference between Delete and Truncate?

Difference 1: Truncate (DDL) is faster than Delete (DML)

Difference 2: Delete can be rollbacked whereas Truncate can't.

Reason being Redo Log Files not maintained for Truncate.

Indexing in Oracle

Ever wondered what Indexing actually does :)

An index is a performance tuning mechanism that allows faster retreival of records.

Searching an indexed table is always faster than a normal table since indexing keeps the records sorted (B-Tree).

In normal search oracle has to scan the entire table, but in an indexed table there is no need to scan the entire table since the records are already sorted.


Index on Single column ->

CREATE INDEX PIndex ON TableName (ColumnName)


Index on multiple columns->

CREATE INDEX PIndex ON TableName (ColumnOne, ColumnTwo)


Following query fetches only the user defined Indexes->

SELECT
i.INDEX_NAME, i.TABLE_NAME, ic.COLUMN_NAME, ic.COLUMN_POSITION, UNIQUENESS
FROM
USER_INDEXES i JOIN USER_IND_COLUMNS ic ON i.INDEX_NAME = ic.INDEX_NAME
WHERE
i.TABLE_NAME IN (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER='CITI_AMWS_CLUSTER_162');


Above you need to enter OWNER = schemaName.


To fetch all available Indexes use this ->

SELECT * FROM ALL_INDEXES;


Following DDL statement can be used to rebuild in Indexes.

ALTER INDEX index_name REBUILD;


Drop Index ->

DROP INDEX index_name;
Home