Thursday 24 November 2016

Printing characters with their count in a String

Total number of Character in ASCII table is 256 (0 to 255). 0 to 31(total 32 character ) is called as ASCII control characters (character code 0-31). 32 to 127 character is called as ASCII printable characters (character code 32-127). 128 to 255 is called as The extended ASCII codes (character code 128-255)

There are multiple solution available with O(n) time and space complexity using Set,Map , O(n2) using Brute force iterating each character element of a String.

Solution 1 : 

But I am representing a solution with O(n) time complexity and In place O(1) space complexity as follow : 



/**

 * @author sachin
 *
 */
public class CountDuplicates {
public static void charsCount(String str){
int[] intArr = new int[256];
char[] charArrInputstr.toCharArray();
int charLength = charArrInput.length;
for (int i = 0; i < charLength; i++) {
intArr[charArrInput[i]]++;
}
int j =0;
for (int c : intArr) {
if(c > 0){
System.out.println( "char=" + (char)j + " and count=" + c );
}
j++;
}
}
public static void main(String[] args) {
String a = "My Name Is Sachin Srivastava and I am a Java Architect passionate "
+ "about writing,blogging & coding , author of tek9g.blogspot.com and vedology.blogspot.com";
charsCount(a);
}
}

Output :


char=  and count=21
char=& and count=1
char=, and count=2
char=. and count=4
char=9 and count=1
char=A and count=1
char=I and count=2
char=J and count=1
char=M and count=1
char=N and count=1
char=S and count=2
char=a and count=15
char=b and count=4
char=c and count=6
char=d and count=4
char=e and count=5
char=f and count=1
char=g and count=9
char=h and count=3
char=i and count=8
char=k and count=1
char=l and count=4
char=m and count=4
char=n and count=7
char=o and count=14
char=p and count=3
char=r and count=4
char=s and count=6
char=t and count=10
char=u and count=2
char=v and count=4
char=w and count=1
char=y and count=2


Solution 2 :

Using a HashMap : O(n) time and space complexity


       
Map<Character, Integer> map = new HashMap<>();
char[] charArrInputstr.toCharArray();
for (char c : charArrInput) {
if(!map.containsKey(c)){
map.put(c, 1);
} else {
map.put(c, map.get(c)+1);
}
}
for (Entry<Character, Integer> entry : map.entrySet()) {
System.out.println("char=" + entry.getKey() + " and count=" + entry.getValue());
}
Output:
char=A and count=1
char=I and count=2
char=J and count=1
char=M and count=1
char=N and count=1
char=S and count=2
char=  and count=21
char=a and count=15
char=b and count=4
char=c and count=6
char=d and count=4
char=e and count=5
char=& and count=1
char=f and count=1
char=g and count=9
char=h and count=3
char=i and count=8
char=k and count=1
char=, and count=2
char=l and count=4
char=m and count=4
char=n and count=7
char=. and count=4
char=o and count=14
char=p and count=3
char=r and count=4
char=s and count=6
char=t and count=10
char=u and count=2
char=v and count=4
char=w and count=1
char=y and count=2
char=9 and count=1


Solution 3 :   Using brute force in the O(n2)   , basically iterating each  n element and comparing and counting remaining  n-1 element  making it quadratic solution with respect to time.

Solution 3 is not recommended , Solution 1 is the best solution and if one not able to do like solution1 then Solution 2 would be simple to use.

Enjoy tek9g  blog and coding !!!!!!!!!

Sunday 20 November 2016

Making PDF Password protected in Java


There are various libraries available through to which a pdf can protected with password encryption.

Full maven repository is available here

But as a developer , I am using here itextpdf library and bouncyCastle libraries to make the PDF password protection.

Following is pom.xml for the dependencies : 

    <dependencies>
           <dependency>
           <groupId>com.itextpdf</groupId>
           <artifactId>itextpdf</artifactId>
          <version>5.2.1</version>
  </dependency>
  <dependency>
       <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.46</version>
    </dependency>

</dependencies>


So most import libraries to use are :

1 . itextpdf-5.2.1.jar 
2 . bcprov-jdk15on-1.46.jar 

Code to implement : 

       

/**
 * @author sachin
 *
 */
public class PdfEncryption {
public static void main(String[] args) {
try {
String outputPdfFile = "/Users/sachin/Desktop/testing.pdf";
String userPassword = "testing_user";
String ownerPassword ="testing_owner"
String pdfContent = "This is the demonstration of the pdf password protection";
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfFile));
writer.setEncryption(userPassword.getBytes(), ownerPassword.getBytes(),
PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128);
document.open();
document.addAuthor("Sachin Srivastava");
document.addCreator("Sachin Srivastava");
document.addSubject("Thanks for your support");
document.addTitle("Please read this");
HTMLWorker htmlWorker = new HTMLWorker(document);
htmlWorker.parse(new StringReader(pdfContent));
document.close();
writer.close();
System.out.println("pdf created from content");
} catch (Exception e) {
System.out.println("error occured in creating pdf from content");
}
}
}


Above  code generates a PDF named testing.pdf with the password protection.

Here PDFWriter setEncryption is used to encrypt the pdf using user password byte
array as a first parameter, owner password byte array as a second parameter, 3rd
parameter as the PDF permission(PdfWriter.ALLOW_PRINTING - 2052 ) and 4th is the
encryption type which is of two type

ENCRYPTION_AES_128
ENCRYPTION_AES_256


So enjoy coding with tek9g tips of encrypting PDF and making it password protected.

Wednesday 16 November 2016

Next higher number with same digits

Finding a next higher number with the same digits is one of the challenging problem to identify a solution with respect to  time space complexity . Any solution which provides in least time and least space would be suitable for the best fit of the solution.

There are multiple solution to this problem :

Solution 1 :

Simplest solution is to find the all permutations of the digits and sort the numbers and then compare with the given number to find next higher number .

Time complexity O(n!) for the solution and not at all suitable for practical cases.It would be worst solution to this problem.

Solution 2 :

Another solution with the O(n) time complexity and O(1) space would be as follow :

       
public static void swap(char[]  charArray, int j , int k){
char temp = charArray[j];
charArray[j] = charArray[k];
charArray[k] = temp;
}
public static void nextHigherInteger(Integer input){
if(input == null || input<=0 ){
return;
}
String s = input.toString();
char[] charArr = s.toCharArray();
int charLength = charArr.length;
int breakPoint = 0;
for (int i = charLength-1; i > 0; i--) {
char last = charArr[i];
char secondLast = charArr[i-1];
if(secondLast < last ){
breakPoint = i-1;
break;
}
if(breakPoint == 0){
System.out.println("This is the highest number");
return;
}
String first = s.substring(0, breakPoint+1);
String second = s.substring(breakPoint+1, charLength);
char[] secondCharArra = second.toCharArray();
Arrays.sort(secondCharArra);//sorting to the second substring
StringBuffer sb2 =new StringBuffer();
sb2.append(first);
for (char c : secondCharArra) {
sb2.append(c);
}          
char[] charArray = sb2.toString().toCharArray();
int j = breakPoint;
int k = ++breakPoint;
while(true){
if(charArray[j] < charArray[k]){
swap(charArray, j, k);
break;
} else {
k++;
}
}
StringBuffer sb3 = new StringBuffer();
for (char c : charArray) {
sb3.append(c);
}  
System.out.println(sb3.toString());
}
public static void main(String[] args) {
//nextHigherInteger(34722641);//34724126
//nextHigherInteger(1234675);//1234756
//nextHigherInteger(23514);//23541
nextHigherInteger(38276);//38627
}

Above mention solution is simple in terms of understanding the logic ,it uses following main points :

1 .  Traverse from tail till the higher sequence is break means from left to right traverse and check that left digit must be higher than right digit , at any point of its less , its a break/pivot point.

2. Divide two substring one for left to the break/pivot point and one for the right of the pivot point.

3. Sort the second string in the ascending order  and compare the first char to rightmost character of first string(x) , if its higher then swap them . If its is less then go for next char of the second string and compare them if its correct then swap it , similarly till the next higher number to  x is found. 

4. Merge first and second string  and your required number would this string.

Time complexity  : O(n) and space O(1) 
Sorting Method : Merge sort of Default Java