Java Code Warm up (my Kata)

Exciting projects and challenges keep you up to date and completely fit.
As a full-stack freelance, you always want to stay fit, even in languages or technologies that are not used in the current project.
For example, between database development and Java development, it is worlds apart.
In this blog, I’ll show some simple methods that I practice several times a week to stay fit in Java. Especially when I am deep down somewhere else.
It’s all about simple things: manipulating strings, sorting, etc. But practicing them helps a lot to stay fit.

The complete Code is to find under:

https://github.com/afikri-code/java-warmup

Let’s start

Generating n-length array of integer (and distinct values):

Sometimes when we want to test some java code, we need to generate arrays or lists to use them as input for our tests. To achieve this I use the class Random from the package java.util. The following are two methods to generate n-length arrays. In the second method, the values of the arrays are distinct.

To generate n-length array, in which it does not matter if the values are distinct or not:

        /**
	 * @param dim, Array dimension
	 * @param bound maxvalue (arr[i] <= bound)
	 * @return
	 */
	public int[] generateIntArr(int dim, int bound) {
		int[] arr = new int[dim];
		Random random = new Random();
		for(int i=0;i<dim;i++) {
			arr[i] = random.nextInt(bound);
		}
		return arr;		
	}

To generate n-length array of distinct integer:

        /**
	 * @param dim , Array dimension
	 * @param bound maxvalue (arr[i] <= bound)
	 * @return
	 */
	public int[] generateIntArrDistinctVals(int dim, int bound) {
		int[] arr = new int[dim];
		int tmpArrSize = 100*dim;
		int currentSize = 0;
		int tmp,tmpMod;
		int[] tmpArr = new int[tmpArrSize];
		Random random = new Random();
		while(currentSize<dim) {
		  tmp = random.nextInt(bound);
		  tmpMod = tmp%tmpArrSize;
		  if(tmpArr[tmpMod]!=tmpMod) {
			  tmpArr[tmpMod] = tmpMod;
			  arr[currentSize++]=tmp;
		  }
		}		
		return arr;
	}

Note: We do not use the Set Data structure to ensure that the array values are distinct. Instead, we use a simple hash function and a temporary array.

Check if the values of an array are distinct: To achieve this we use a Set data structure.

/**
 * @param arr
 * @return
 */
public boolean isArrDistinct(int[] arr) {
    Set<Integer> tmpSet = new HashSet<>();
    for(int i=0;i<arr.length;i++) {
        //if an element already exist, the add function
        // return false
        if(!tmpSet.add(arr[i]))
            return false;
    }
    return true;

}

Check if array is sorted:

        /**
	 * @param arr
	 * @return
	 */
	public boolean isArrSorted(int[] arr) {
		for(int i = 1;i< arr.length;i++) {
			if(arr[i]<arr[i-1])
				return false;
		}
		return true;
	}

Merge Sort:

        /**
	 * @param left
	 * @param right
	 * @return
	 */
	int[] mergeArr(int[] left, int[] right) {
		int[] arr = new int[left.length+right.length];
		int currentSize =0;
		int j=0;
		for(int i=0;i<left.length;i++) {
			while(j<right.length && right[j]<left[i]) {
				arr[currentSize++] = right[j++];
			}
			arr[currentSize++] = left[i];
		}
		for(int i=j;i<right.length;i++) {
			arr[currentSize++]=right[i];
		}
		
		return arr;
	}
	
	/**
	 * @param arr
	 * @return
	 */
	public int[] sortMerge(int[] arr) {
		if(arr.length == 1) {
			return arr;
		}
		int[] left = new int[arr.length/2];
		int[] right = new int[arr.length - left.length];
		for(int i=0;i<left.length;i++) {
			left[i] = arr[i];
		}
		for(int i=0;i<right.length;i++) {
			right[i] = arr[i+left.length];
		}
		left = sortMerge(left);
		right = sortMerge(right);
		return mergeArr(left,right);
	}

Quicksort

        /**
	 * @param arr
	 * @param begin
	 * @param end
	 * @return
	 */
	int partitionForQuickSort(int[] arr,int begin, int end) {
		int pi = arr[(begin+end)/2];
		int i=begin-1;
		int j=end+1;
		int tmp;
		while(true) {
			do {
				i++;
			}while(arr[i]<pi);
			do {
				j--;
			}while(arr[j]> pi);

			if(i<j) {
				tmp = arr[i];
				arr[i]=arr[j];
				arr[j]=tmp;
			}else {
				return j;
			}
		}

	}
	
	public void quickSort(int[] arr, int begin,int end) {
		if(begin<end) {
			int q = partitionForQuickSort(arr,begin,end);
			quickSort(arr,begin,q);
			quickSort(arr,q+1,end);
		}
		
	}

Find Longest Common Sequence

/**
	 * @param s1
	 * @param s2
	 * @return
	 */
	public String findLongestCommonSequence(String s1, String s2) {
		String longStr;
		String shortStr;
		String tmp = null;
		if(s1.length() > s2.length()) {
			longStr = s1;
			shortStr = s2;
		}else {
			longStr = s2;
			shortStr = s1;
		}
		
		int length = shortStr.length();
		
		for(int i=length;i>0;i--) {
			int begin = 0;
			while(begin+i<=length) {
			   tmp = shortStr.substring(begin, i+begin++);
			   if(longStr.contains(tmp)) {
				   System.out.println(tmp);
				   return tmp;
			   }
			}
		}
		
		
		return null;
	}

Find Longest Palindrome

        /**
	 * @param word
	 * @return
	 */
	public String findLongestPalindrome(String word) {
		int length = word.length();
		int j ;
		for(int l=length;l>0;l--) {
			j=0;
			while(j+l<=length) {
				char[] a = word.substring(j, j+l).toCharArray();
				int i=a.length/2+1;
				
				while(i-->0 && a[i]==a[a.length - 1-i]);
				if(i==-1) {
					return new String(a);
				}
				
				j++;
			}
			
		}
		return "";
	}

Reverse an Integer value

        /**
	 * e.g. input = 54321 output = 12345
	 * @param input
	 * @return
	 */
	//Reverse an Integer value
	public int reverseIneger(int input) {
		int output = 0;		
		do {
		//be aware if 10*output > Integer.max_value!!
		  output = 10*output+input%10;
		  input /=10;
		}while(input>0);
		return output;
	}

Records Versioning in an SQL table: Removing duplicates

It happens that one want to protocol all changes of records of a table in the same table. This by using two timestamp columns „valid_from“ and „valid_to“. So that there is always exactly one version of a record for a given time.

As part of a data migration in a project, I was faced with a situation that I have different versions that have the same content. Let me illustrate this with an example:

create table tbl_a (
                      id number
                      ,valid_from timestamp(6)
                      ,valid_to timestamp(6)
                      ,element_id number
                      ,k_type varchar2(10)
);

Fill the table with few columns

insert into tbl_a 
select 123456 id,
       systimestamp + numtodsinterval(1, 'SECOND') +
       numtodsinterval(rownum - 1, 'MINUTE') valid_from,
       systimestamp + numtodsinterval(rownum, 'MINUTE') valid_to,
       case   when mod(rownum,12) in (4,5,6) then 123 when mod(rownum,12) in (7,8,9) then 124
                 when mod(rownum,12) in (10,11,0) then 125  else null end element_id, 
               case   when mod(rownum,12) in (4,5,6) then 'NP' when mod(rownum,12) in (7,8,9) then 'JP'
                 when mod(rownum,12) in (10,11,0) then 'KB'  else null end k_type
          from dual
        connect by level < 25;
commit;
select * from tbl_a order by valid_from desc

In this example, we see that we have six versions of each record.
But only two versions, correspond to a real change. So the goal is to remove the non-real changes to each record and the values of „valid_from“ and „valid_to“ need not have a gap. The right „valid_from“ and „valid_to“ are marked in red.

Duplicates are removed
with the right version Begin and end

This can be achieved with the following SQL:

SELECT id,
       MAX(valid_to) valid_to,
       MIN(valid_from) valid_from,
       element_id,
       k_type
  FROM (SELECT id,
               valid_to,
               valid_from,
               element_id,
               k_type,
               ROW_NUMBER() OVER(PARTITION BY id ORDER BY valid_to) - ROW_NUMBER() OVER(PARTITION BY id, element_id, k_type ORDER BY valid_to) rrr
          FROM (SELECT id,
                       valid_to,
                       valid_from,
                       element_id,
                       k_type,
                       LEAD(k_type || element_id, 1, 'x') OVER(PARTITION BY id ORDER BY valid_to) R,
                       LAG(k_type || element_id, 1, 'x') OVER(PARTITION BY id ORDER BY valid_to) RR
                  FROM tbl_a T
                 ORDER BY valid_to) S
         WHERE (NVL(R, 'y') <> NVL(RR, 'y') OR
               NVL(r, 'y') <> NVL(k_type || element_id, 'y'))) Q
 GROUP BY id, element_id, k_type, rrr
 order by 3 desc

That was just an example. In my case, the table consisted of several dozens of columns and has several millions of records.
You can use pl sql to dynamically generate this SQL for a general case.