USACO : calfflac
by Abhijeet Kashnia
Just to remind myself later how chaotic my code can be and see my progress as time goes by, this time I want to paste two of my solutions, the first one where I tried to extract common functions and made things too complicated, and the second where I kept things simple. Abstraction and its object oriented cousins are not so helpful when you just want to implement an algorithm,
It seems that if the logic is too convoluted, it gets way out of hand and out of control. Its symptoms are thinking that one more if condition here or there will fix the problem. This only makes the code inordinately long, and then it is just downhill from there.
On the other hand, keeping things simple, having code that runs for the simple cases first, makes it easier to predict where the rest of the test cases are failing.
I also seem to write 90 % of the solution quickly and get stuck trying to pass one or the other test case. That last 10% seems to be taking at least half of the time. Its not the difficulty of the problem, but probably my inexperience. Maybe I should start thinking much more carefully about the corner cases.
I have also noticed that there is a bit of something that I take along from one solution that helps me in the next, cutting those few seconds off my personal time. I am getting faster, from idea to implementation.
Failed Solution:
It seems that if the logic is too convoluted, it gets way out of hand and out of control. Its symptoms are thinking that one more if condition here or there will fix the problem. This only makes the code inordinately long, and then it is just downhill from there.
On the other hand, keeping things simple, having code that runs for the simple cases first, makes it easier to predict where the rest of the test cases are failing.
I also seem to write 90 % of the solution quickly and get stuck trying to pass one or the other test case. That last 10% seems to be taking at least half of the time. Its not the difficulty of the problem, but probably my inexperience. Maybe I should start thinking much more carefully about the corner cases.
I have also noticed that there is a bit of something that I take along from one solution that helps me in the next, cutting those few seconds off my personal time. I am getting faster, from idea to implementation.
Failed Solution:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class calfflac2
{
private static String data = null;
private static int maxLength=0, pointer=0;
public static void main(String[] args) throws NumberFormatException, IOException
{
// BufferedReader reader = new BufferedReader(new FileReader(new File("calfflac.in")));
// data = reader.readLine();
// PrintWriter out = new PrintWriter(new File("calfflac.out"));
data="Confucius say: Madam, I'm Adam.";
longestPalindrome();
// out.print(data.substring(pointer, pointer+maxLength));
// out.close();
System.out.println(data.substring(pointer, pointer+maxLength));
System.exit(0);
}
private static boolean isSpecial(char myChar)
{
return myChar=='\n' || myChar==',' || myChar=='\'' || myChar==' ' || myChar==':';
}
private static void longestPalindrome()
{
int upper=0, lower=0, thisLength=0;
// for(int k=0;k<2;k++) {
upper=0;
lower=0;
thisLength=0;
for(int i=0;i<data.length();i++) {
if(isSpecial(data.charAt(i))) // dont' make starting character as special
continue;
// if(k==0) {
// lower=upper=i;
// }
// else {
lower=i;
upper=i+1;
// }
// Just increment and decrement pointers while matching continues, and ignore special characters.
while(true) {
if(lower<0 || upper>data.length()-1) {
break;
}
// ensure that characters are valid.
if(isSpecial(data.charAt(lower))) {
lower--;
continue;
}
if(isSpecial(data.charAt(upper))) {
upper++;
continue;
}
if(Character.toLowerCase(data.charAt(lower))==Character.toLowerCase(data.charAt(upper))) {
thisLength=upper-lower+1;
if(thisLength>maxLength) {
maxLength=thisLength+2;
pointer=lower-1;
}
}
lower--;
upper++;
}
}
}
// }
}
Working solution:
/*
ID: abhi
LANG: JAVA
TASK: calfflac
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class calfflac
{
private static String data="";
public static void main(String[] args) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(new File("calfflac.in")));
String line="";
while ((line = reader.readLine()) != null) {
data += line + "\n";
}
longestPalindrome();
System.exit(0);
}
private static void longestPalindrome() throws FileNotFoundException
{
int upper=0, lower=0, thisLength=0, maxLength=0, pointer=-1;
// int countSpecial=0, storeSpecial=0;
PrintWriter writer = new PrintWriter(new File("calfflac.out"));
for(int k=0;k<2;k++) {
for(int i=0;i<data.length();i++) {
upper=i+k; lower=i;
thisLength=0;
// countSpecial=0;
while(lower>=0 && upper<data.length()
&& (Character.toLowerCase(data.charAt(lower))==Character.toLowerCase(data.charAt(upper)))) {
thisLength=upper-lower +1 ;
if(thisLength>maxLength) {
maxLength=thisLength;
pointer=lower;
// storeSpecial= countSpecial;
}
lower--;
while(lower>0 && isSpecial(data.charAt(lower))) {
lower--;
// countSpecial++;
}
upper++;
while(upper<data.length() && isSpecial(data.charAt(upper))) {
upper++;
// countSpecial++;
}
}
}
}
// writer.println(maxLength-storeSpecial);
int count=0;
for(int i=0;i<maxLength;i++) {
if(isSpecial(data.charAt(pointer+ i))) {
count++;
}
}
writer.println(maxLength-count);
writer.println(data.substring(pointer, pointer+maxLength));
writer.close();
}
private static boolean isSpecial(char myChar)
{
return !( (myChar>=65 && myChar<=90) || (myChar>=97 && myChar<=122));
}
}