I'm trying to make an AI for a hangman game, part of which requires counting all occurrences of each possible character in the word list. I'm planning on culling the word list before this counting to make things run faster (by first culling out all words that are not the same length as the guessable phrase, and then by culling out words that do not match the guessed characters).
The problem I am having is in the code below. Somehow, it always returns a list of e's that are the correct length (matching the number of possible characters). I'm not sure exactly what I'm doing wrong here, but the problem is definitely somewhere in countCharacters.
MethodicComputer(){
guessable = parseGuessable();
wordList = parseText();
priorities = countCharacters(guessable);
}
public char guessCharacter(String hint){
char guess = 0;
System.out.println(guessable);
System.out.println(priorities);
guess = priorities.charAt(0);
priorities = priorities.replaceAll("" + guess, "");
return guess;
}
private String countCharacters(String possibleChars){
charCount = new Hashtable();
String orderedPriorities = "";
char temp = 0;
char adding = 0;
int count = 0;
int max = 0;
int length = possibleChars.length();
for (int i = 0; i<length; i++){
temp = possibleChars.charAt(i);
count = wordList.length() - wordList.replaceAll("" + temp, "").length();
charCount.put(temp, count);
}
while (orderedPriorities.length() < length){
for (int i = 0; i < possibleChars.length(); i++){
temp = possibleChars.charAt(i);
if (max < (int) charCount.get(temp)){
max = (int) charCount.get(temp);
adding = temp;
}
}
orderedPriorities += adding;
possibleChars = possibleChars.replaceAll("" + adding, "");
}
return orderedPriorities;
}
The problem is that I did not update the max variable, so it never entered the if statement and updated the adding variable. A simple addition of
max = 0;
to the end of the while loop fixed it.
Related
First I uploaded the file I'm using, the constitution. Then, I created two arrays, one for the length of the alphabet, the second to compute the frequency. I created a while loop to read every line in the document and count the frequency of every letter, I just can't figure out how to compute each as a percentage of each letter because after I'm going to put it into a bar chart.
int [ ]lettersLabels = new int [26];
int [ ]lettersFrequency = new int [26];
String line;
//initialize arrays
letterLabels = 0;
lettersFrequency = 0;
Scanner sc = new Scanner(constitution);
while(sc.hasNextLine())
{
line = sc.nextLine();
line = sc.toLowerCase();
char[] characters = line.toCharArray();
for (int i = 0; i< characters.length ; i++)
{
if((characters[i] >='a') && (characters[i]<='z'))
{
lettersLabels[characters[i] -'a' ]++;
}
}
}
for (int i = 0; i < 26; i++)
{
lettersFrequency = 'a' + [characters[i] -'a' ]++;
lettersFrequency = lettersFrequency / 100;
System.out.println(lettersFrequency);
}
Percentage is ratio * 100 (1/2 = 0.5 = (0.5 * 100)% = 50%), and the ratio here is lettersLabels[i] / totalLetters. So, in order to find the percentage, you just use lettersFrequency[i] = (double) lettersLabels[i] / (double) totalLetters * 100;. So, you might need a variable totalLetters at the beginning to count the number of letters.
You have a mistake in your code, which is initializing arrays with 0. You have already initialized the arrays with int[] arr = new int[26];, so you don't need those two lines, which will give an error since initializing arrays with an int is the wrong type. Also, when setting some part of lettersFrequency to something, you need to specify the index, like lettersFrequency[i], and instead of using characters when its out of scope to get the characters, so instead you have to use the letterLabels array.
Hope this works!
Here I've fix some of the errors with description see the code comments for explanation :
int [ ]lettersLabels = new int [26];
int [ ]lettersFrequency = new int [26];
String line;
int totalLetter =0; // needed to calculate %
// No need to initialize, it's already initialized with 0 values.
// remove those lines.
//initialize arrays
// letterLabels = 0;
// lettersFrequency = 0;
Scanner sc = new Scanner(constitution);
while(sc.hasNextLine())
{
line = sc.nextLine();
// need to lower case the current line
line = line.toLowerCase();
char[] characters = line.toCharArray();
for (int i = 0; i< characters.length ; i++)
{
if((characters[i] >='a') && (characters[i]<='z'))
{
// lets count the letter frequency.
totalLetter++;
lettersFrequency[characters[i] -'a' ]++;
}
}
}
// get rid of divide by zero exception
if(totalLetter ==0) totalLetter =1;
for (int i = 0; i < 26; i++)
{
char ch = 'a'+i;
// let's count the parentage of each letter.
double parcentage = (lettersFrequency[i]*100.00)/totalLetter;
System.out.println("parcentage of "+ ch+ " is: " +lettersFrequency +"%");
}
I am trying to get the contents of a string, and store it in the last row of my 2D array here is what I have so far:
char[][] square = new char[5][5];
String number = new String("three");
for(int k = number.length() - 1; k >= 0; k--)
{
square[4][k] = number.charAt(k);
}
The output the code is giving me is the string in non reversed order.
Isn't this the logic for reversing a string? All I am doing here is setting the fourth column, and all rows starting at the end of the string to it's value. What am I missing?
Thanks
just walk through the loop by hand.
The first time through, k is 4.
So, square[4][4] is set to the character returned by .charAt(4), which is an 'e'.
then square[4][3] becomes 'e', ... and square[4][0] becomes 't'.
square[4] now reads t,h,r,e,e.
You've basically reversed both ends. Try this:
for (int k = 0; k < number.length(); k++) {
square[4][k] = number.charAt(number.length() - k - 1);
}
Yes, because you're not reversing it. You're setting the same character back again at the same position. If you need it reversed then the logic should be
square[4][number.length() - (k + 1)] = number.charAt(k);
You need a different index beyond square[4][k] when you are also copying the value from number.charAt(k) - that is, you are copying the characters backwards (but into the array also backward). There is no need to call new String(String). You could do
char[][] square = new char[5][5];
String number = "three";
for (int i = 0; i < number.length(); i++) {
int k = number.length() - i - 1;
square[4][k] = number.charAt(i);
}
But I would prefer a StringBuilder and StringBuilder.reverse() myself. Like,
char[][] square = new char[5][5];
String number = "three";
square[4] = new StringBuilder(number).reverse().toString().toCharArray();
My code is meant to find the most frequent codon from a file that contains a lonf string of DNA (i.e. CTAAATCGATGGCGATGATAAATG...). starting at the initial position pos, every three characters makes up one codon. The problem I have is that whenever I run the code, it tell me that the string index is out of range. I know that the issue is in the line
str = line.substring(idx, idx + 2);
but don't know how to fix it. Also, I am not sure whether I am counting frequencies correctly. I needed to increment the value of every key that is seen more than once.
public static void findgene(String line){
int idx, pos;
int[] freq = new int[100];
String str;
//pos is the position to start at
pos = 0;
idx = pos;
for(int i = 0; i < line.length(); i++){
if(idx >= 0){
//makes every three characters into a codon
str = line.substring(idx, idx + 2);
//checks if the codon was previously seen
if(genes.containsKey(str)){
genes.put(str, freq[i]++);
}
idx = idx + 2;
}
}
}
You are incrementing idx by 2 with each iteration of the loop. However, you did not impose any restriction on the upper limit of idx.
Thus the the parameter of the substring() function soon goes out of range in the line:
str = line.substring(idx, idx + 2);
What you need to do is change the condition to:
if(idx+2<=line.length()){
//code here
}
I need help sorting this array. Here's the code, it doesn't sort at all it just keeps the array the way it was entered. I've been stuck on this for a day now and can't figure anything out. Help would be appreciated. Here's the code I have:
// sortGrossPay takes an array and sorts it by descending order
public static void sortGrossPay(String[] employeeNames, double[][] employeeInformation,
int numberEmployees, int GROSS_PAY)
{
int numberOfColumns = employeeInformation[HOURS].length;
double[] oneRow = new double[numberOfColumns];
int maxIndex;
String strTemp;
for(int i = 0; i < numberEmployees - 1; i++) {
maxIndex = i;
double maxGross = employeeInformation[i][GROSS_PAY];
// Compare value of current maxIndex with the next number, if the next number is
// greater than the maxIndex, set its index as the new max
for(int j = i + 1; j < numberEmployees; j++) {
if (employeeInformation[i][GROSS_PAY] > employeeInformation[maxIndex][GROSS_PAY]) {
maxIndex = j;
maxGross = employeeInformation[i][GROSS_PAY];
}
} // End nested for loop
// Replace name at current minimum index with the name found at i
strTemp = employeeNames[maxIndex] = employeeNames[i];
employeeNames[maxIndex] = employeeNames[i];
employeeNames[i] = strTemp;
oneRow = employeeInformation[maxIndex];
employeeInformation[maxIndex] = employeeInformation[i];
employeeInformation[i] = oneRow;
} // End for loop
} // End method
I think your first problem is coming from this assignment:
strTemp = employeeNames[maxIndex] = employeeNames[i];
try changing that line of code to this:
strTemp = employeeNames[maxIndex];
The assignment you're doing assigns the value of employeeNames[i] to both employeeNames[maxIndex] and strTemp. You need strTemp to contain the value at employeeNames[maxIndex], but that's being overwritten before you have a chance to store it.
That is why your array isn't changing at all.
Secondly, the check in your nested for loop should look like this:
if (employeeInformation[j][GROSS_PAY] > employeeInformation[maxIndex][GROSS_PAY])
and the line inside of the if statement should look like this:
maxGross = employeeInformation[j][GROSS_PAY];
note the j (you're checking index i).
Need java function to find the longest duplicate substring in a string
For instance, if the input is “banana”,output should be "ana" and we have count the number of times it has appeared in this case it is 2.
The solution is as below
public class Test{
public static void main(String[] args){
System.out.println(findLongestSubstring("i like ike"));
System.out.println(findLongestSubstring("madam i'm adam"));
System.out.println(findLongestSubstring("When life hands you lemonade, make lemons"));
System.out.println(findLongestSubstring("banana"));
}
public static String findLongestSubstring(String value) {
String[] strings = new String[value.length()];
String longestSub = "";
//strip off a character, add new string to array
for(int i = 0; i < value.length(); i++){
strings[i] = new String(value.substring(i));
}
//debug/visualization
//before sort
for(int i = 0; i < strings.length; i++){
System.out.println(strings[i]);
}
Arrays.sort(strings);
System.out.println();
//debug/visualization
//after sort
for(int i = 0; i < strings.length; i++){
System.out.println(strings[i]);
}
Vector<String> possibles = new Vector<String>();
String temp = "";
int curLength = 0, longestSoFar = 0;
/*
* now that the array is sorted compare the letters
* of the current index to those above, continue until
* you no longer have a match, check length and add
* it to the vector of possibilities
*/
for(int i = 1; i < strings.length; i++){
for(int j = 0; j < strings[i-1].length(); j++){
if (strings[i-1].charAt(j) != strings[i].charAt(j)){
break;
}
else{
temp += strings[i-1].charAt(j);
curLength++;
}
}
//this could alleviate the need for a vector
//since only the first and subsequent longest
//would be added; vector kept for simplicity
if (curLength >= longestSoFar){
longestSoFar = curLength;
possibles.add(temp);
}
temp = "";
curLength = 0;
}
System.out.println("Longest string length from possibles: " + longestSoFar);
//iterate through the vector to find the longest one
int max = 0;
for(int i = 0; i < possibles.size();i++){
//debug/visualization
System.out.println(possibles.elementAt(i));
if (possibles.elementAt(i).length() > max){
max = possibles.elementAt(i).length();
longestSub = possibles.elementAt(i);
}
}
System.out.println();
//concerned with whitespace up until this point
// "lemon" not " lemon" for example
return longestSub.trim();
}
}
This is a common CS problem with a dynamic programming solution.
Edit (for lijie):
You are technically correct -- this is not the exact same problem. However this does not make the link above irrelevant and the same approach (w.r.t. dynamic programming in particular) can be used if both strings provided are the same -- only one modification needs to be made: don't consider the case along the diagonal. Or, as others have pointed out (e.g. LaGrandMere), use a suffix tree (also found in the above link).
Edit (for Deepak):
A Java implementation of the Longest Common Substring (using dynamic programming) can be found here. Note that you will need to modify it to ignore "the diagonal" (look at the Wikipedia diagram) or the longest common string will be itself!
In Java : Suffix Tree.
Thanks to the ones that have found how to solve it, I didn't know.