package com.interview.string;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
/**
* http://www.geeksforgeeks.org/rearrange-a-string-so-that-all-same-characters-become-at-least-d-distance-away/
*
*/
public class RearrangeDuplicateCharsdDistanceAway {
class CharCount implements Comparable<CharCount>{
char ch;
int count;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ch;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CharCount other = (CharCount) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (ch != other.ch)
return false;
return true;
}
private RearrangeDuplicateCharsdDistanceAway getOuterType() {
return RearrangeDuplicateCharsdDistanceAway.this;
}
@Override
public String toString() {
return "CharCount [ch=" + ch + ", count=" + count + "]";
}
@Override
public int compareTo(CharCount cc) {
if(this.count >= cc.count){
return -1;
}else{
return 1;
}
}
}
public boolean rearrangeExactKDistanceAway(char input[],int d){
PriorityQueue<CharCount> heap = new PriorityQueue<CharCount>();
Map<Character,Integer> map = new HashMap<Character,Integer>();
for(int i=0; i < input.length; i++){
int count = 1;
if(map.containsKey(input[i])){
count = map.get(input[i]);
count++;
}
map.put(input[i], count);
input[i] = 0;
}
for(Character ch : map.keySet()){
CharCount cc = new CharCount();
cc.ch = ch;
cc.count = map.get(ch);
heap.add(cc);
}
while(heap.size() > 0){
CharCount cc = heap.poll();
int i;
for(i=0; i < input.length && input[i] != 0; i++);
if(i == input.length){
return false;
}
while(cc.count > 0 && i < input.length){
input[i] = cc.ch;
i = i + d;
cc.count--;
}
if(cc.count > 0){
return false;
}
}
return true;
}
private void getAllFeasibleCharacters(char output[], int k,int pos,Set<Character> allChars){
for(int i = pos-1; i > pos -k && i >=0; i--){
allChars.remove(output[i]);
}
}
public boolean rearrangeAtleastkDistanceAway(char input[],int k){
Map<Character,Integer> map = new HashMap<Character,Integer>();
for(int i=0; i < input.length; i++){
int count = 1;
if(map.containsKey(input[i])){
count = map.get(input[i]);
count++;
}
map.put(input[i], count);
input[i] = 0;
}
return rearrangeAtleastkDistanceAway(map, input, 0, k);
}
public boolean rearrangeAtleastkDistanceAway(Map<Character,Integer> charCount,char output[],int pos,int k){
if(pos == output.length && charCount.size() == 0){
return true;
}
Set<Character> allChars = new HashSet<Character>();
for(char ch : charCount.keySet()){
allChars.add(ch);
}
getAllFeasibleCharacters(output,k,pos,allChars);
for(char ch : allChars){
output[pos] = ch;
int c = charCount.get(ch);
if(c -1 == 0){
charCount.remove(ch);
}else{
charCount.put(ch, c-1);
}
boolean r = rearrangeAtleastkDistanceAway(charCount, output, pos+1, k);
if(r){
return true;
}
charCount.put(ch, c);
}
return false;
}
public static void main(String args[]){
String str = "ABBACCCCDD";
char input[] = str.toCharArray();
RearrangeDuplicateCharsdDistanceAway rdc =new RearrangeDuplicateCharsdDistanceAway();
boolean r =rdc.rearrangeAtleastkDistanceAway(input, 3);
if(r){
for(char ch : input){
System.out.print(ch + " ");
}
}else{
System.out.println("Not possible");
}
}
}