Showing posts with label Algorithms. Show all posts
Showing posts with label Algorithms. Show all posts

Sunday, November 15, 2020

Permutation - Heap's Algorithm

 This is a little bit of an experimentation that I did recently to figure out a reasonable code to get all possible permutations of a set of characters. 


So say given a set of characters "ABC", my objective is to come up code which can spit out "ABC", "ACB", "BAC", "BCA", "CBA", "CAB". 


The approach I took is to go with the definition of permutation itself, so with "ABCD" as the set of characters a 4 slot that needs to be filled.



The first slot can be filled by any of A, B, C, D, in 4 ways:


The second slot by any of the remaining 3 characters, so with "A" in the first slot - 


The third slot by the remaining 2 characters, so with "A", "B" in the first two slots:
And finally, the fourth slot by the remaining 1 character, with say "A", "B", "C" in the first 3 slots:



In total, there would be 4 for the first slot * 3 for the 2nd slot * 2 for the 3rd slot * 1 for the 4th slot - 24 permutations altogether. 

I can do this in place, using an algorithm that looks like this:






A trace of flow and the swaps is here:
The only trick here is that the code does all the holding of characters and getting it into the right place in place by swapping the right characters to the right place and restoring it at the end of it. 

This works well for a reasonably sized set of characters - reasonable because for just 10 characters, there would be 3,628,800 permutations. 

An algorithm that works even better, though a complete mystery to me how it actually functions(well explained here if anybody is interested), is the Heap's Algorithm. Here is a java implementation of it: It very efficiently does one swap per permutation, which is still high but better than the approach that I have described before. 


In a sample perumutation of 8 characters, which generates 40320 permutations, the home cooked version swaps 80638 times, and the Heap's algorithm swaps 40319 times! thus proving its efficacy.

Tuesday, December 23, 2014

Solving "Water buckets" problem using Scala

I recently came across a puzzle called the "Water Buckets" problem in this book, which totally stumped me.


You have a 12-gallon bucket, an 8-gallon bucket and a 5-gallon bucket. The 12-gallon bucket is full of water and the other two are empty. Without using any additional water how can you divide the twelve gallons of water equally so that two of the three buckets have exactly 6 gallons of water in them?


I and my nephew spent a good deal of time trying to solve it and ultimately gave up.

I remembered then that I have seen a programmatic solution to a similar puzzle being worked out in the "Functional Programming Principles in Scala" Coursera course by Martin Odersky.

This is the gist to the solution completely copied from the course:



and running this program spits out the following 7 step solution! (index 0 is the 12-gallon bucket, 1 is the 8-gallon bucket and 2 is the 5-gallon bucket)

Pour(0,1) 
Pour(1,2) 
Pour(2,0) 
Pour(1,2) 
Pour(0,1) 
Pour(1,2) 
Pour(2,0)

If you are interested in learning more about the code behind this solution, the best way is to follow the week 7 of the Coursera course that I have linked above, Martin Odersky does a fantastic job of seemingly coming up with a solution on the fly!.

Wednesday, December 25, 2013

java.util.Random in Java 8

One of the neat features of java.util.Random class in Java 8 is that it has been retrofitted to now return a random Stream of numbers.


For eg, to generate an infinite stream of random doubles between 0(inclusive) and 1(exclusive):

Random random = new Random();
DoubleStream doubleStream = random.doubles();

or to generate an infinite stream of integers between 0(inclusive) and 100(exclusive):

Random random = new Random();
IntStream intStream = random.ints(0, 100);


So what can this infinite random stream be used for, I will demonstrate a few scenarios, do keep in mind though that since this is an infinite stream, any terminal operations has to be done once the stream has been made limited in some way, otherwise the operation will not terminate!

For eg. to get a stream of 10 random integers and print them:
intStream.limit(10).forEach(System.out::println);

Or to generate a list of 100 random integers :

List<Integer> randomBetween0And99 = intStream
                                       .limit(100)
                                       .boxed()
                                       .collect(Collectors.toList());


For gaussian pseudo-random values, there is no stream equivalent of random.doubles(), however it is easy to come up with one with the facility that Java 8 provides:

Random random = new Random();
DoubleStream gaussianStream = Stream.generate(random::nextGaussian).mapToDouble(e -> e);

Here, I am using the Stream.generate api call passing in a Supplier which generates the next gaussian with the already available method in Random class.


So now to do something a little more interesting with the stream of pseudo-random doubles and the stream of Gaussian pseudo-random doubles, what I want to do is to get the distribution of doubles for each of these two streams, the expectation is that the distribution when plotted should be uniformly distributed for pseudo-random doubles and should be normal distributed for Gaussian pseudo-random doubles.

In the following code, I am generating such a distribution for a million pseudo-random values, this uses a lot of facilities provided by the new Java 8 Streams API:

Random random = new Random();
DoubleStream doubleStream = random.doubles(-1.0, 1.0);
LinkedHashMap<Range, Integer> rangeCountMap = doubleStream.limit(1000000)
        .boxed()
        .map(Ranges::of)
        .collect(Ranges::emptyRangeCountMap, (m, e) -> m.put(e, m.get(e) + 1), Ranges::mergeRangeCountMaps);

rangeCountMap.forEach((k, v) -> System.out.println(k.from() + "\t" + v));

and this code spits out data along these lines:
-1	49730
-0.9	49931
-0.8	50057
-0.7	50060
-0.6	49963
-0.5	50159
-0.4	49921
-0.3	49962
-0.2	50231
-0.1	49658
0	50177
0.1	49861
0.2	49947
0.3	50157
0.4	50414
0.5	50006
0.6	50038
0.7	49962
0.8	50071
0.9	49695

and similarly generating a distribution for a million Gaussian pseudo-random values:
Random random = new Random();
DoubleStream gaussianStream = Stream.generate(random::nextGaussian).mapToDouble(e -> e);
LinkedHashMap<Range, Integer> gaussianRangeCountMap =
        gaussianStream
                .filter(e -> (e >= -1.0 && e < 1.0))
                .limit(1000000)
                .boxed()
                .map(Ranges::of)
                .collect(Ranges::emptyRangeCountMap, (m, e) -> m.put(e, m.get(e) + 1), Ranges::mergeRangeCountMaps);

gaussianRangeCountMap.forEach((k, v) -> System.out.println(k.from() + "\t" + v));

Plotting the data gives the expected result:

For a pseudo-random Data:


And for Gaussian Data:


Complete code is available in a gist here - https://gist.github.com/bijukunjummen/8129250

Tuesday, August 7, 2012

Mergesort using Fork/Join Framework

The objective of this entry is to show a simple example of a Fork/Join RecursiveAction, not to delve too much into the possible optimizations to merge sort or the relative advantages of using Fork/Join Pool over the existing Java 6 based implementations like ExecutorService.

The following is a typical implementation of a Top Down Merge sort algorithm using Java:

import java.lang.reflect.Array;

public class MergeSort {
 public static <T extends Comparable<? super T>> void sort(T[] a) {
  @SuppressWarnings("unchecked")
  T[] helper = (T[])Array.newInstance(a[0].getClass() , a.length);
  mergesort(a, helper, 0, a.length-1);
 }
 
 private static <T extends Comparable<? super T>> void mergesort(T[] a, T[] helper, int lo, int hi){
  if (lo>=hi) return;
  int mid = lo + (hi-lo)/2;
  mergesort(a, helper, lo, mid);
  mergesort(a, helper, mid+1, hi);
  merge(a, helper, lo, mid, hi);  
 }

 private static <T extends Comparable<? super T>> void merge(T[] a, T[] helper, int lo, int mid, int hi){
  for (int i=lo;i<=hi;i++){
   helper[i]=a[i];
  }
  int i=lo,j=mid+1;
  for(int k=lo;k<=hi;k++){
   if (i>mid){
    a[k]=helper[j++];
   }else if (j>hi){
    a[k]=helper[i++];
   }else if(isLess(helper[i], helper[j])){
    a[k]=helper[i++];
   }else{
    a[k]=helper[j++];
   }
  }
 }

 private static <T extends Comparable<? super T>> boolean isLess(T a, T b) {
  return a.compareTo(b) < 0;
 }
}

To quickly describe the algorithm -
The following steps are performed recursively:

  1.  The input data is divided into 2 halves
  2.  Each half is sorted
  3. The sorted data is then merged

Merge sort is a canonical example for an implementation using Java Fork/Join pool, and the following is a blind implementation of Merge sort using the Fork/Join framework:

The  recursive task in Merge sort can be succinctly expressed as an implementation of RecursiveAction -


 private static class MergeSortTask<T extends Comparable<? super T>> extends RecursiveAction{
  private static final long serialVersionUID = -749935388568367268L;
  private final T[] a;
  private final T[] helper;
  private final int lo;
  private final int hi;
  
  public MergeSortTask(T[] a, T[] helper, int lo, int hi){
   this.a = a;
   this.helper = helper;
   this.lo = lo;
   this.hi = hi;
  }
  @Override
  protected void compute() {
   if (lo>=hi) return;
   int mid = lo + (hi-lo)/2;
   MergeSortTask<T> left = new MergeSortTask<>(a, helper, lo, mid);
   MergeSortTask<T> right = new MergeSortTask<>(a, helper, mid+1, hi);
   invokeAll(left, right);
   merge(this.a, this.helper, this.lo, mid, this.hi);
   
   
  }
  private void merge(T[] a, T[] helper, int lo, int mid, int hi){
   for (int i=lo;i<=hi;i++){
    helper[i]=a[i];
   }
   int i=lo,j=mid+1;
   for(int k=lo;k<=hi;k++){
    if (i>mid){
     a[k]=helper[j++];
    }else if (j>hi){
     a[k]=helper[i++];
    }else if(isLess(helper[i], helper[j])){
     a[k]=helper[i++];
    }else{
     a[k]=helper[j++];
    }
   }
  }
  private boolean isLess(T a, T b) {
   return a.compareTo(b) < 0;
  }
 }

MergeSortTask above implements a compute method, which takes in a array of values, split it up into two parts, creates a MergeSortTask out of each of the parts and forks off two more tasks(hence it is called RecursiveAction!). The specific API used here to spawn of the task is invokeAll which returns only when the submitted subtasks are marked as completed. So once the left and right subtasks return the result is merged in a merge routine.

Given this the only work left is to use a ForkJoinPool to submit this task. ForkJoinPool is analogous to the ExecutorService used for distributing tasks in a threadpool, the difference to quote the ForkJoinPool's API docs:

A ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of employing work-stealing: all threads in the pool attempt to find and execute subtasks created by other active tasks (eventually blocking waiting for work if none exist)

This is how the task of submitting the task to the Fork/Join Pool looks like:

 public static <T extends Comparable<? super T>> void sort(T[] a) {
  @SuppressWarnings("unchecked")
  T[] helper = (T[])Array.newInstance(a[0].getClass() , a.length);
  ForkJoinPool forkJoinPool = new ForkJoinPool(10);
  forkJoinPool.invoke(new MergeSortTask<T>(a, helper, 0, a.length-1));
 }

A complete sample is also available here: https://github.com/bijukunjummen/algos/blob/master/src/main/java/org/bk/algo/sort/algo04/merge/MergeSortForkJoin.java

Saturday, March 24, 2012

Some Bit manipulation tricks


1. Let's start with a simple one:
n<<1 is equivalent to n*2
More generally:
n<<i is equivalent to n*2i

Along the same lines:
n>>1 is equivalent to n/2
n>>i is equivalent to n/2i


2. To find the index of the most significant bit of a number or -1 if 0:
A few examples:
for 3 (11) it is 1
for 121(1111001) it is 6

An algorithm for this involves iterating the bits of a number and looks something like this in java - essentially keep right shifting until the value is 0:
int findIndexOfMostSignificantBit(int n){
       int s=0;
        while(n!=0){
            s++;
            n = n >> 1;
        }
        return s>0?s-1:-1;
    } 

3. Multiply two numbers using bit manipulation:
I look at it this way:
a*b with b represented in binary can be thought of as a*(x*2^0 + x*2^1....x*2^n),
int multiply(int a, int b){
     int sum = 0;
     for (int i=0;b!=0;i++){
      if((b&1)!=0){
       sum += (a<<i);
      }
      b = b>>1;
     }
     return sum;
    }

4. What does (n &(n-1))==0 mean?
Well, it is a way to check if a number can be represented as a power of 2 -
eg 8&7 becomes 1000 & 0111 which is 0, 7 & 6 becomes 0111 & 0110 which is NOT 0

5. Getting a bit at index i:

(n & (1<<i))!=0

6. Setting a bit at index i:
n=n|(1<<i)

7. Clearing the bits between index i and j:
A sample for this is 121(1111001) clear bits between 4 and 2 yields in binary 1100001

The trick here is to create a mask which is all 1's except between i and j:
this mask can be created in two parts, the right part of the mask is created by left shifting 1 j places and subtracting 1 which results in all the bits from 0 to j-1 being set with 1.

the left part of the mask is created by negating 0 which yields all 1's, followed by shifting left i+1 places which puts 0's upto ith place.
int clearBits(int n, int i, int j){
    int left = (~0)<<i+1;
    int right = (1<<(j))-1;
    
    return n&(left|right);
}

Tuesday, July 26, 2011

"n" slots - continued..

A different java implementation, closer to being a good functional implementation, but not quite there:

public List<String> fillNSlots(int n){
        return fillNSlotsWithPrefix(0, n, "");
        
    }
    
    private List<String> fillNSlotsWithPrefix(int counter, int  n, String prefix){
        if (counter==n-1){
            return new ArrayList<String>(Arrays.asList(new String[]{prefix + "0", prefix + "1"})); 
        }else{
            List<String> result1 = fillNSlotsWithPrefix(counter+1, n , prefix + "0");
            result1.addAll(fillNSlotsWithPrefix(counter+1, n , prefix + "1"));
            return result1;
        }
    }

It is not quite there, as there is still a need to hold an intermediate state with a temporary variable, result1 above, which could have been avoided had List supported an API which adds an element and returns itself or returns a new list.

The following is an equivalent implementation in scala:

def fillNSlots(n:Int):List[String] = {
        fillNSlotsWithPrefix(0,n,"")
    }

    def fillNSlotsWithPrefix(counter:Int, n: Int, prefix:String): List[String] = {
        if (counter==(n-1))
            (prefix+"0")::(prefix+"1")::List()
        else
            fillNSlotsWithPrefix(counter+1, n, prefix+"0"):::fillNSlotsWithPrefix(counter+1, n, prefix+"1")
    }

Sunday, July 24, 2011

"n" slots - different ways of filling it

The problem is simple - Given "n" slots, find all possible different configurations to fill the slots:
For "2" slots, the possible configurations are - [00, 01, 10, 11]
For "3" slots, the possible configurations are - [000, 001, 010, 011, 100, 101, 110, 111]

Here is a test for any solution:

@Test
    public void test2Slots() {
        String[] slotsAnswer = {"00","01", "10", "11"};
        assertThat(fillNSlots(2), hasItems(slotsAnswer));
    }

    @Test
    public void test3Slots() {
        String[] slotsAnswer = {"000", "001", "010", "011", "100", "101", "110", "111"};
        assertThat(fillNSlots(3), hasItems(slotsAnswer));
    }

    @Test
    public void test5Slots() {
        String[] slotsAnswer = {"00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111"};
        assertThat(fillNSlots(5), hasItems(slotsAnswer));
    }

I have a naive solution to start with:
public List<String> fillNSlots(int n){
        List<String> result = new ArrayList<String>();
        fillNSlotsWithPrefix(result, n, "");
        return result;
    }
    
    private void fillNSlotsWithPrefix(List<String> result, int n, String prefix){
        if (n==0){
            result.add(prefix);
        }else{
            fillNSlotsWithPrefix(result, n-1, prefix + "0");
            fillNSlotsWithPrefix(result, n-1, prefix + "1");
        }
    }
This solution works, however state is being passed(an arraylist of result) with each of the "fillNSlotsWithPrefix" methods recursive calls. A pure functional method, however would not have had this side effect. I will fix this implementation to be more functional over the course of next week.

Tuesday, May 31, 2011

Tower of Hanoi in Scala

Had a little fun with scala after 2 months, an implementation of Tower of Hanoi:
object Hanoi{
    def move(n:Int, fromTower:String, toTower:String, usingTower:String):Unit = {
        if (n==0) return
        move(n-1, fromTower, usingTower, toTower);
        println("Moving from " + fromTower + " to " + toTower)
        move(n-1, usingTower, toTower, fromTower);
    }
}

Sunday, September 12, 2010

Karate Chop - An Imperative and Functional implementation

Karate Chop is a Kata about implementing binary search five different ways. I could come up with 2 obvious ways - an imperative style with iteration and a functional style based on the solution inspired by this site . So here goes:

Imperative:

package org.bk.karatechop

class KarateChop {
 def chop(aNumber:Int, anArray:Array[Int]):Int = {
  var minIndex=0
  var maxIndex = anArray.length-1
  while(minIndex<=maxIndex){
   var midIndex = (minIndex+maxIndex)/2
   var atMidIndex = anArray(midIndex)
   if (aNumber>atMidIndex){
    minIndex=midIndex+1
   }else if(aNumber<atMidIndex){
    maxIndex=midIndex-1
   }else{
    return midIndex
   }
  }
  
  -1
  
 }
}
Functional: 
package org.bk.karatechop

class KarateChopRecursive {
 def chop(aNumber:Int, anArray:Array[Int]):Int = {
  
  def recurse(low:Int, high:Int):Option[Int] = { 
   (low + high)/2 match {
    case _ if high < low => None
    case mid if aNumber < anArray(mid)  => recurse(low, mid - 1)
    case mid if aNumber > anArray(mid)  => recurse(mid + 1, high)
    case mid => Some(mid)
   }   
  }
  
  recurse(0,anArray.length-1).getOrElse(-1)
  
  
 }
}