Created
April 3, 2016 20:46
-
-
Save jianminchen/5e3002256642454eae747da2bde26ab3 to your computer and use it in GitHub Desktop.
Reverse Shuffle merge - get score 16.67 - still need to continue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace ReverseMergeString | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Console.WriteLine(reverseMerge(Console.ReadLine())); | |
} | |
/* | |
* Failed test case: | |
* bdabaceadaedaaaeaecdeadababdbeaeeacacaba | |
* output: | |
* aaaaaabaaceededecbdb | |
* aaaaaabaaceededecbdb | |
* aaaaaabaaceaeaaadead" | |
* Julia's output "cdeadababdbeaeeacacaba" string | |
* Failed test case: | |
* djjcddjggbiigjhfghehhbgdigjicafgjcehhfgifadihiajgciagicdahcbajjbhifjiaajigdgdfhdiijjgaiejgegbbiigida | |
* | |
* output: | |
* aaaaabccigicgjihidfiejfijgidgbhhehgfhjgiibggjddjjd | |
*/ | |
public static string reverseMerge(string s) | |
{ | |
if (!canBeReverseMerged(s)) | |
return ""; | |
int len = s.Length; | |
int half = len / 2; | |
int[] A = getCountArray(s); | |
int[] skipLog = getHalf(A); | |
String output = ""; | |
for (int i = len -1; i >=0 && output.Length < half; i-- ) | |
{ | |
char c = s[i]; | |
if (outputCheckSayNO(A, output, c)) | |
continue; | |
if (haveToAdd(skipLog, c) || | |
( firstOneNonzero(skipLog, c) || | |
!greedyCheckForwardSkip(skipLog, c) | |
)) | |
output += c; | |
else | |
{ | |
if (!canDecrement(skipLog, c)) | |
return ""; // something is wrong | |
} | |
} | |
return output; | |
} | |
private static bool outputCheckSayNO(int[] A, string s, char c) | |
{ | |
int count = getNo(s, c); | |
if (count >= A[c - 'a']/2) | |
return true; | |
else | |
return false; | |
} | |
private static int getNo(string s, char c) | |
{ | |
int count = 0; | |
foreach (char si in s) | |
if (si == c) | |
count++; | |
return count; | |
} | |
private static bool needContinue(int[] skipLog) | |
{ | |
for(int i=0;i<26;i++) | |
{ | |
if (skipLog[i] > 0) | |
return true; | |
} | |
return false; | |
} | |
/* | |
* | |
*/ | |
private static bool haveToAdd(int[] skipLog, char c) | |
{ | |
return (skipLog[c - 'a'] == 0); // design flaw - | |
} | |
private static bool canDecrement(int[] A, char c) | |
{ | |
int index = c - 'a'; | |
A[index]--; | |
return (A[index] >= 0); | |
} | |
/* | |
* Skip rules - only two : | |
* 1. First, if there is one to skip before the input char | |
* 2. Second, if the char is the first one in the list, alway go to true | |
*/ | |
private static bool greedyCheckForwardSkip(int[] A, char c) | |
{ | |
int end = c - 'a'; | |
for (int i = 0; i < end; i++) | |
{ | |
if (A[i] > 0) | |
return true; | |
} | |
return false; | |
} | |
/* | |
* Skip rules - only two: | |
* 1. First, if there is one to skip before the input char | |
* 2. Second, if the char is the first one in the list, alway go to true | |
*/ | |
[Obsolete] | |
private static bool greedyCheckBackwardSkip(int[] A, char c) | |
{ | |
int start = c - 'a'; | |
for (int i = 25; i > start; i--) // bug: index problem - why I am still need debugger here!!! 'c'-'a', should be c-'a' | |
{ | |
if (A[i] > 0 && i != start) // bug: A[i], should be i | |
return true; | |
} | |
return false; | |
} | |
// c is first char nonzero | |
private static bool firstOneNonzero(int[] A, char c) | |
{ | |
int end = c - 'a'; | |
for (int i = 0; i < end; i++) | |
{ | |
if (A[i] > 0 ) | |
return false; | |
} | |
return true; | |
} | |
private static int[] getHalf(int[] A) | |
{ | |
int[] ret = new int[26]; | |
for(int i=0; i<26; i++) | |
{ | |
ret[i] = A[i] / 2; | |
} | |
return ret; | |
} | |
private static bool isHalf(int[] B, int[] A) | |
{ | |
for(int i=0;i<26;i++) | |
{ | |
if (B[i] * 2 == A[i]) | |
continue; | |
else | |
return false; | |
} | |
return true; | |
} | |
// assume both string have same length | |
// because it is reverse string | |
private static string smallOne(string tmpS1, string tmpS2) | |
{ | |
string s1 = reverse(tmpS1); | |
string s2 = reverse(tmpS2); | |
int len = s1.Length; | |
for(int i=0;i<len;i++) | |
{ | |
if (s1[i] < s2[i]) | |
return tmpS1; | |
else if (s1[i] > s2[i]) | |
return tmpS2; | |
} | |
// both are the same, any one | |
return tmpS1; | |
} | |
private static string reverse(string s) | |
{ | |
StringBuilder newS = new StringBuilder(); | |
for (int i = s.Length - 1; i >= 0; i--) | |
newS.Append(s[i].ToString()); | |
return newS.ToString(); | |
} | |
private static bool canBeReverseMerged(string s) | |
{ | |
if (s == null || s.Length == 0) return true; | |
int[] A = new int[26]; | |
for(int i=0; i < s.Length;i++) | |
{ | |
A[s[i]-'a']++; | |
} | |
for(int i=0;i<26;i++) | |
{ | |
if (A[i] % 2 == 1) | |
return false; | |
} | |
return true; | |
} | |
private static int[] getCountArray(string s) | |
{ | |
int[] A = new int[26]; | |
if (s == null || s.Length == 0) return A; | |
for (int i = 0; i < s.Length; i++) | |
{ | |
A[s[i] - 'a']++; | |
} | |
return A; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment