Java, generate a text - java

I have a problem with a part of my program. In the following code 27 is the number of letters of our alphabet; list_extended is an objcet of type Hashtable(StringBuffer,Integer), containing all strings of length n+1 in the text with the number of occurrences; list_extended is built correctly because I have already controlled this part. The aim is : for every repetition of the outer for we take te last n characters of text generated, and for every letter of the alphabet we count the number of occurrences in list_extended of the n+1 characters obtained by adding the character to the last n characters of text_generated; then we choose the letter with the biggest number of occurrences. The result I obtain is that occurrences contains all 0's, why ? The code
int index;
int[] occurrences = new int[27];
StringBuffer curr_word;
for(int x = 0; x < m; x++){ // m is the number of characters the user wants to add
curr_word = new StringBuffer(text_generated.substring(x, x+n)); // n is an integer entered previously, initially text_generated is formed by n characters
for(int j = 0; j < 27; j++){
if(list_extended.get(curr_word.append(array[j]))==null)
occurrences[j] = 0;
else
occurrences[j] =(int) list_extended.get(curr_word.append(array[j]));
}
index = 0;
for(int j = 1; j < 27; j++){
if(occurrences[j] > occurrences[index])
index = j;
}
text_generated = text_generated.append(array[index]);
}
System.out.println("The text generatd is \n" + text_generated.toString());

Because you create new object curr_word, but you didn't put it in list_extended, so every time you check
if(list_extended.get(curr_word.append(array[j]))==null)
will be null and
occurrences[j] will be 0

Related

How to count inputs in an array in java

I have n inputs.
these inputs are numbers from 1 to 100.
I want to output the number that appears less than the other ones; also if there are two numbers with the same amount of appearance, I want to output the number that is less than the other one.
I wrote this code but it doesn't work!
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt(), max=0 , ans=-1;
int[] counter = new int[n];
for(int i=0; i<n; i++)
counter[scanner.nextInt()]+=1;
for(int j=1; j<=100; j++){
if(counter[j]>max)
max=counter[j];
}
for (int i=1; i<=max; i++){
if(counter[i]>0)
if(ans==-1 || counter[ans]>counter[i] || (counter[ans] == counter[i] && i<ans))
ans=i;
}
System.out.print(ans);
There’s a couple of problems with your code, but the main one is the last for loop: You are trying to find the first (ie lowest) number whose counter is equal to max, so your loop should be from 1 to n, not 1 to max.
Another problem is if you are using the number, which is in the range 1-n, as your array index, you need an array of size n+1, not n.
I pinched this from another question regarding the title of yours:
i = input.nextInt (); while (i != 0) { counts [i]++; i = input.nextInt (); } That method increments the number at the position of the user input in the counts array, that way the array holds the number of times a number occurs in a specific index, e.g. counts holds how often 3 occurs.
counter array should contain frequency values for the numbers from 1 to 100 inclusive.
That is, either a shift by 1 should be used when counting the frequency:
int[] counter = new int[100];
for (int i = 0; i < n; i++) {
counter[scanner.nextInt() - 1]++;
}
or 101 may be used as the length of counter array thus representing values in the range [0..100], without shifting by 1.
int[] counter = new int[101];
for (int i = 0; i < n; i++) {
counter[scanner.nextInt()]++;
}
The minimal least frequent number can be found in a single loop (assuming that the counter length is 101).
int minFreq = 101, answer = -1;
for(int j = 1; j <= 100; j++) {
if (counter[j] > 0 && counter[j] < minFreq) { // check valid frequency > 0
minFreq = counter[j];
answer = j;
}
}
System.out.println(answer);
For a wider range of input values (e.g. including negative values) of a relatively small count it is better to use a hashmap instead of a large sparse array.

Figuring out a proper way to read in data

https://drive.google.com/a/navasotaisd.org/file/d/0B3eMFMufj6uVaVNpR0JYNnV4OTQ/view
Okay, so the problem above asks that you read in a file with a message and, using and x, y coordinate system, find the characters being read in and print out the character of that index value. I honestly have tried multiple solutions with making and array of arraylists, a arraylist of arraylists and many other failed data structures. All I need to know, is how would go about reading in the message so that I can search for it?
File f = new File("cipher.in");
f.createNewFile();
Scanner scan = new Scanner(f);
int numOfLines = scan.nextInt();
scan.nextLine();
ArrayList<Character> list = new ArrayList();
String code = "";
for (int i = 0; i < numOfLines; i++) {
code = scan.nextLine();
for (int j = 0; j < code.length(); j++) {
list.add(code.charAt(j));
}
}
int index = 0;
char[][] matrix = new char[(int)(list.size())][(int)(list.size())];
for (int r = 0; r < matrix.length; r++) {
for (int c = 0; c < matrix[r].length; c++) {
matrix[r][c] = list.get(index);
index++;
if(index>=list.size())
index--;
}
}
Sorry if this problem is a bit long. It's for my class I need to turn this problem in to be able to make a 100 in the gradebook. I'm just utterly stuck and frustrated.
Try to use a hash table to store the data. You will be able to search for it later on.
The key fits quite nicely into a two-dimensional charcter array (char[][]). I would consider reading the first line (which specifies the number of lines on the key (rows of the array), and then construct the array. You have a constraint defined that a row can be no longer than 100 characters long so you can now define the complete "map".
After that i would read each line of the key, use an operator as charAt(index) and fill the map.
From there you have a very convenient structure to lookup the messages in the next part of the assignment.
Try this out , this is you code with changes and comments so that you can understand the changes and the way this code works based on the instruction in your link, I did not try to compile it, so if it has any compilation errors try to fix them. I kept your code and commented out the items that are not needed so that you can look at the differences,
File f = new File("cipher.in");
//f.createNewFile(); //* you are overwriting the file here
Scanner scan = new Scanner(f);
int numOfLines = scan.nextInt();
//str = scan.nextLine(); //* you just skipped one line from the numOfLInes
//ArrayList<Character> list = new ArrayList(); //* this does not help, you need to index into the line number, char index
TreeMap charMap = new TreeMap(); //* use this to map the line number to a char array
String code = "";
for (int i = 0; i < numOfLines; i++) {
strubg code = scan.nextLine();
charMap.put(i, code.toCharArray()); //* map the line number with the char array of each line
//for (int j = 0; j < code.length(); j++) {
// list.add(code.charAt(j));
//}
}
int numOfMessageLines = scan.nextInt(); //* get the number of message lines next
for (int i = 0; i < numOfMessageLines; i++) {
string str = scan.nextLine();
string[] pairs = str.split(" "); //* each line has several key pairs for line number char number seprated by spaces
ArrayList<char> list = new ArrayList(); //* this does not help, you need to index into the line number, char index
for(int j=0; j<pairs.length; j++)
{
string[] st = pairs[j].trim().split(","); //* example 2,13 indicate line 2 character 13 non zero indexed
int lineNum = Integer.parse(st[0]) - 1; //* zero indexed line number since we stored the lines in zero index map
int charNum = Integer.parse(st[1]) - 1; //* zero indexed char number since we stored the char array in zero indexed array
char[] chars = charMap.get(lineNum); //* get the char array for this line number
char c = chars[charNum]; //* get the character for the first message
list.add(c);
}
String message = new String(list.toArray()); //* construct the message from the char array
System.out.println(message);
}
//int index = 0;
//char[][] matrix = new char[(int)(list.size())][(int)(list.size())];
//for (int r = 0; r < matrix.length; r++) {
// for (int c = 0; c < matrix[r].length; c++) {
// matrix[r][c] = list.get(index);
// index++;
// if(index>=list.size())
// index--;
// }
//}

Finding repeats in a 2D array

I have made a program that outputs the number of repeats in a 2D array. The problem is that it outputs the same number twice.
For example: I input the numbers in the 2D array through Scanner: 10 10 9 28 29 9 1 28.
The output I get is:
Number 10 repeats 2 times.
Number 10 repeats 2 times.
Number 9 repeats 2 times.
Number 28 repeats 2 times.
Number 29 repeats 1 times.
Number 9 repeats 2 times.
Number 1 repeats 1 times.
Number 28 repeats 2 times.
I want it so it skips the number if it has already found the number of repeats for it. The output should be:
Number 10 repeats 2 times.
Number 9 repeats 2 times.
Number 28 repeats 2 times.
Number 29 repeats 1 times.
Number 1 repeats 1 times.
Here is my code:
import java.util.Scanner;
public class Repeat
{
static Scanner leopard = new Scanner(System.in);
public static void main(String [] args)
{
final int ROW = 10; //Row size
final int COL = 10; //Column size
int [][] num = new int[ROW][COL];
int size;
//Get input
size = getData(num);
//Find repeat
findRepeats(num, size);
}
public static int getData(int [][] num)
{
int input = 0, actualSize = 0; //Hold input and actualSize of array
System.out.print("Enter positive integers (-999 to stop): ");
//Ask for input
for(int i = 0; i < num.length && input != -999; i++)
{
for(int j = 0; j < num[i].length && input != -999; j++)
{
input = leopard.nextInt();
//Check if end
if(input != -999)
{
num[i][j] = input;
actualSize++;
}
}
}
System.out.println();
return actualSize;
}
public static void findRepeats(int [][] num, int size)
{
int findNum;
int total = 0, row = 0, col = 0;
for(int x = 0; x < size; x++)
{
//Set to number
findNum = num[row][col];
//Loop through whole array to find repeats
for(int i = 0; i < num.length; i++)
{
for(int j = 0; j < num[i].length; j++)
{
if(num[i][j] == findNum)
total++;
}
}
//Cycle array to set next number
if(col < num[0].length-1)
col++;
else
{
row++; //Go to next row if no more columns
col = 0; //Reset column number
}
//Display total repeats
System.out.println("Number " + findNum + " appears " + total + " times.");
total = 0;
}
}
}
I know why it is doing it, but I cannot figure out how to check if the number has already been checked for it to skip that number and go to the next number. I cannot use any classes or code that is not used in the code.
Since you cannot use anything other than this, lets say, basic elements of Java consider this:
Make another temporary 2D array with two columns (or just two separate arrays, personally I prefer this one). On the start of the algorithm the new arrays are empty.
When you take a number (any number) from the source 2D structure, first check if it is present in the first temporary array. If it is, just increment the value (count) in the second temporary array for one (+1). If it is not present in the first tmp array, add it to it and increase the count (+1) in the second at the same index as the newly added number in the first (which should be the last item of the array, basically).
This way you are building pairs of numbers in two arrays. The first array holds all your distinct values found in the 2D array, and the second one the number of appearances of the respective number from the first.
At the and of the algorithm just iterate the both arrays in parallel and you should have your school task finished. I could (and anyone) code this out but we are not really doing you a favor since this is a very typical school assignment.
It's counting the number two times, first time it appears in the code and second time when it appears in the code.
To avoid that keep a system to check if you have already checked for that number. I see you use check int array but you haven't used it anywhere in the code.
Do this,
Put the number in the check list if you have already found the count of it.
int count = 0;
check[count] = findNum;
count++;
Note: You can prefill you array with negative numbers at first in order to avoid for having numbers that user already gave you in input.
Next time in your for loop skip checking that number which you have already found a count for
for(int x = 0; x < size; x++) {
findNum = num[row][col];
if(check.containsNumber(findNUm)) { //sorry there is no such thing as contains for array, write another function here which checks if a number exists in the array
//skip the your code till the end of the first for loop, or in other words then don't run the code inside the for loop at all.
}
}
Frankly speaking I think you have just started to learn coding. Good luck! with that but this code can be improved a lot better. A piece of advice never create a situation where you have to use 3 nested for loops.
I hope that you understood my solution and you know how to do it.
All answers gives you some insight about the problem. I try to stick to your code, and add a little trick of swap. With this code you don't need to check if the number is already outputted or not. I appreciate your comments, structured approach of coding, and ask a question as clear as possible.
public static void findRepeats(int [][] num, int size)
{
int findNum;
int total = 1, row = 0, col = 0;
int [] check = new int[size];
while(row < num.length && col < num[0].length)
{
//Set to number
findNum = num[row][col];
//Cycle array to set next number
if(col < num[0].length-1)
col++;
else
{
row++; //Go to next row if no more columns
col = 0; //Reset column number
}
//Loop through whole array to find repeats
for(int i = row; i < num.length; i++)
{
for(int j = col; j < num[i].length; j++)
{
if(num[i][j] == findNum) {
total++;
//Cycle array to set next number
if(col < num[0].length-1)
col++;
else
{
row++; //Go to next row if no more columns
col = 0; //Reset column number
}
if(row < num.length - 1 && col < num[0].length -1)
num[i][j] = num[row][col];
}
}
}
//Display total repeats
System.out.println("Number " + findNum + " appears " + total + " times.");
total = 1;
}
}
you can use a HashMap to store the result. It Goes like this:
// Create a hash map
HashMap arrayRepeat = new HashMap();
// Put elements to the map
arrayRepeat.put(Number, Repeated);

Why does Java give runtime error when depositing data into an array using a "for" loop?

I wanted to write code that reads a word stored as a String variable. The program should loop through each character in the word and update an array that contains the frequency with which each letter occurs.
The letters in the alphabet (A to Z) can be referenced by "freq[1]" to "freq[26]".
However, when I try to run my program, I get an error that says:
java.lang.ArrayIndexOutOfBoundsException: -64
at ReadWords.main(ReadWords.java:17)
Here is the code I used:
public class ReadWords
{
public static void main (String[] args)
{
String line = "This is a line of text. That's not exciting";
line = line.toLowerCase();
int[] freq = new int[27];
for (int i = 0; i < line.length(); i++)
{
int letter = line.charAt(i) - 96;
freq[letter]++;
}
for (int i = 0; i < freq.length - 1; i++)
{
System.out.println(freq[i]); //prints all elements in the array
}
}
}
Because you are reading space characters (ASCII 32) with your letters. Its value is 32, and when you subtract 96, you get -64, obviously not a valid array index.
I don't think you want to count spaces, so skip them; don't process them.
You'll want to skip other punctuation characters as well, with ' being ASCII value 39, and . being ASCII value 46.
Your error
Like rgettman said, you're including the spaces in your analysis of the frequence. Simply add an if-statement.
for (int i = 0; i < line.length(); i++)
{
int letter = line.charAt(i) - 96;
if (letter > 0 && letter < 27) freq[letter]++;
}
if (letter > 0 && letter < 27) makes sure that the char that you're at in your String is in fact a letter from a - z
Helpful points
Also, in your second for-loop, it won't display the frequency of 'z', and it will display the frequency as position 0 in the array, which holds nothing (position 1 is 'a').
You need to change this:
for (int i = 0; i < freq.length - 1; i++)
to this:
for (int i = 1; i < freq.length; i++)
This way it includes element 27, which is freq[26], which is where the 'z' frequency is. It also will ignore element 1, which is freq[0]. Try it. Or you could change the size of your freq array to 26, and subtract 97 from the line.charAt(i) and then change the if-statement I gave you in your first for-loop to
if (letter > -1 && letter < 26). And then use for (int i = 0; i < freq.length; i++).
Display the letter with the frequency
Use this line of code to display the char corresponding to the frequency as well:
System.out.println((char)(i + 96) + ": " + freq[i]);
Or if you did what I said where you changed the size of the freq array and made the frequency of 'a' at position 0, use this line:
System.out.println((char)(i + 97) + ": " + freq[i]);
I guess the easiest way to do this would be to only check for lower case alphabets (97-122 ASCII values).
Below is the modified version of your code.
public static void main(String[] args) {
String line = "This is a line of text. That's not exciting";
line = line.toLowerCase();
int[] freq = new int[27];
for (int i = 0; i < line.length(); i++) {
/*Only use lower case alphabets ranging from 97 to 122.
The below if should omit all other unwanted characters from your string.*/
if (line.charAt(i) > 96
&& line.charAt(i) < 123) {
/* Subtract by 97 to start your array from 0 for a(value 97)*/
int letter = line.charAt(i) - 97;
freq[letter]++;
}
}
for (int i = 0; i < freq.length - 1; i++) {
System.out.println((char)(i+97) + " : " + freq[i]); // prints all elements in the array
}
}

Radix sorting code confusion

I have a question about this algo:
(Slide taken from here.)
int N = a.length;
int[] count = new int[R];
for (int i = 0; i < N; i++)
count[a[i]+1]++;
for (int k = 1; k < 256; k++)
count[k] += count[k-1];
for (int i = 0; i < N; i++)
temp[count[a[i]++]] = a[i]
for (int i = 0; i < N; i++)
a[i] = temp[i];
Can someone elaborate about the 3rd for loop where we move the records from a[] to temp[]?
I know after we accumulate counts they're supposed to be some sort of offset. So we can insert the letters in proper place in temp[].
I'm just not sure what the a[i]++ is doing in there. (<-main question) I know where referencing the letter in the count array, but why do we increment the letter too? Did we change letters? Thanks.
Grateful for any help.
it looks like a typo:
it should be:
temp[count[a[i]]++]
the next element should go into the next empty space
in step1 prepares for adds type_i counts to cnt_{i+1}, this way making space for type_i elements...
step2 is a prefix on the counts
step3 uses counts as R index pointers and sends all elements from a to its final destination
invariant holded at this step:
count[ x ] points to the next empty space where an type_x element can be placed (or there are no more x elements in the input)

Categories