How to use a list to populate a grid? - java

I am trying to get this code to read in a text file and then populate a 15x15 grid with the numbers from the file. What it is doing is only populating the grid with 0's. I am not sure how to fix it, but I think the issue is with how I am trying to use list.indexOf() in the loop.
I have tried switching to use list.get(i) or using j, which has not worked the way I need it to.
public Grid(String fileName) throws FileNotFoundException {
//reading file using scanner
Scanner sc = new Scanner(new File(fileName));
//first number is the dimension for rows
this.rows = sc.nextInt();
//since it is square matrix second dimension is same as first
this.cols = this.rows;
grid = new boolean[rows][cols];
String longNumber = sc.next();
List<Integer> list = new ArrayList<>();
for(char ch : longNumber.toCharArray()) {
list.add( Integer.valueOf(String.valueOf(ch)));
}
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
//reading from file 1 and 0 if 1 then store true else store false in grid
if (list.indexOf(i) == 1)
grid[i][j] = true;
else
grid[i][j] = false;
}
}
I am getting an output showing a 15x15 block of 0's, instead of the 1's and 0's that are being read in from the text file. The text file should be read in and displayed (along with a count of blobs or clumps of 1's), but this is not happening. If you need the rest of the code, please let me know. I am required to read in a file, which contains an int (15) which is used to make the grid, and then 15 lines of 1's and 0's, which should be displayed in the same way when the program works properly.

Why are you converting it into a List<Integer>? You can simply work with String that you got from the file.
For each row, you'll have to get a String and then for each of such a String you can do charAt() to check what is the character there and store true or false in grid accordingly.
The code will look something like this:
this.rows = sc.nextInt();
//since it is square matrix second dimension is same as first
this.cols = this.rows;
grid = new boolean[rows][cols];
for (int i = 0; i < rows; i++) {
String longNumber = sc.next();
for (int j = 0; j < cols; j++) {
//reading from file 1 and 0 if 1 then store true else store false in grid
grid[i][j] = (longNumber.charAt(j) == 1);
}
}
Notice that I've placed String longNumber = sc.next() in the outer loop.
HTH

Related

How do you take a 2D array from a text file, and "copy" it into another array using charAt

I was working through a project and I have to use charAt to continuously add elements of an array from a text file to a new array that i would have specified. The size of the array differs depending on the text file being used so it is best to assume that the contents of the file are unknown, however i will provide an example.
I keep on getting a "StringIndexOutOfBoundException" when i run my code and i am not sure why, or how to fix it.
What the code should be doing is taking the user input to get the exact text file location, then it will be reading that line by line and adding that to a new array. The first two lines of the text file array are the array row and column size.
my code is as follows:
public static void main(String[] args) throws FileNotFoundException
{
System.out.println("Enter the location of the board file using the FULL PATH NAME.");
Scanner input = new Scanner(System.in);
String n = input.nextLine();
input.close();
File a = new File(n);
Scanner sc = new Scanner(a);
int row = sc.nextInt();
int col = sc.nextInt();
char[][] board = new char[row][col];
for (int numRow = 0; numRow < row+1; numRow ++)
{
String string = sc.next();
for (int numCol = 0; numCol < col+1; numCol++)
{
board[row][col] = string.charAt(numCol);
}
}
sc.close();
GridGame game = new GridGame (row, col, board);
game.playGame();
An example input text file:
10 10
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
TWWWWWWWWW
The issue you are facing is because a Java array has 0-based index i.e. the index of the first element is 0 and that of the last element is array.length - 1. Therefore, your loop with the variable as the index of the array should not go beyond array.length - 1. Your terminating condition, numRow < row+1 is taking the value of numRow up to the length of the array instead of array.length - 1.
Replace
for (int numRow = 0; numRow < row+1; numRow ++)
{
String string = sc.next();
for (int numCol = 0; numCol < col+1; numCol++)
{
board[row][col] = string.charAt(numCol);
}
}
with
for (int r = 0; r < row && sc.hasNextLine(); r++) {
board[r] = sc.nextLine().toCharArray();
}
The other concept you need to understand is a 2-D array in Java an array of arrays i.e. board[0] should hold the array of characters from the first line of the file, board[1] should hold the array of characters from the second line of the file and so on. Now, if you want to access the 4th character of the 3rd line from the file, you can access it as board[2][3].
The last but not the least is regarding closing the Scanner for System.in. You should never close this Scanner because it also closes the System.in. So, you should remove the line, input.close() from your code.
Update
You can write the above mentioned single loop as a nested loop as well but it is unnecessary.
for (int r = 0; r < row && sc.hasNextLine(); r++) {
char[] lineChars = sc.nextLine().toCharArray();
for(int c = 0; c < col; c++) {
board[r][c] = lineChars [c];
}
}
You need a nested loop in order to access/process individual characters but to store/access/process each row of a 2-D array, you do not need a nested loop. As I have already mentioned, a 2-D array is an array of 1-D arrays and therefore to access each of these 1-D arrays (not individual elements inside these 1-D arrays), you need a single loop, not a nested loop.

Convert 1d array into 2d array using nested for loops

Im trying to scan a file and create a 1D array for each line, then immediately following the creation of that array copy into the first row of a 2D array. I've gotten my code to work for only the first row of the file. It won't move onto the next line. it copies the same line as it traverses the whole 2d array. i know that happens because the counter for the scanning the next line doesn't increase before it reaches the end of the 2d array. how can i increase the counter for scanning the next line? heres my code: (tempString is the 1D array already created before this loop)
for(int i = 0; i < 7; i++){
tempString = scnr.nextLine().split(" ");
//add lines to 2d array
for(int r = 0; r < 7; r++){
int x = 0; //moves along each element in tempString
for(int c = 0; c < tempString.length; c++){
temp[r][c] = Double.parseDouble(tempString[x]);
x++;
}
}
}
You have 3 loops, but you only need two. Each input row read from the file will become a row of the 2-D array :
for(int r = 0; r < 7; r++){
tempString = scnr.nextLine().split(" ");
temp[r] = new double[tempString.length];
for(int c = 0; c < tempString.length; c++){
temp[r][c] = Double.parseDouble(tempString[c]);
}
}
I am not quite sure with what exactly you need. But what I have derived from the question is that you have a file and you need to split it in a 2D array, in which the columns should contain the individual items within each line and each row should be in a new line.
My recommendation is to use ArrayList which will handle the dynamic lengths for you.
See the below example:
Say I have a file 'text.txt' which contains some data like this
abc def ghi
jhl mnop qrs uv
wx yz
Then here is a program which forms a 2D array, first dimension containing each row and the second dimension containing tokens from each line.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
public class Split {
public static void main(String args[]){
ArrayList<ArrayList<String>> columns = new ArrayList<ArrayList<String>>();
columns.add(new ArrayList<String>());//Col 1
columns.add(new ArrayList<String>());//Col 2
columns.add(new ArrayList<String>());//Col 3
BufferedReader br = null;
try
{
br = new BufferedReader(new FileReader("src\\text.txt"));
String sCurrentLine;
int j=0;
while ((sCurrentLine = br.readLine()) != null) {
String sLine[] = sCurrentLine .split(" ");
for(int i = 0; i < sLine.length; i++)
{
columns.get(j).add(sLine[i]);
}
j++;
}
for(ArrayList<String> line:columns){
for(String tokens:line)
System.out.println(tokens);
System.out.println();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
If this is not what you need, please try to elaborate your question further if possible with examples.
Please note that I'm using spaces (" ") to split the tokens, you can replace it by anything that you are using.
I hope it helps :)

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--;
// }
//}

2d boolean array with input values

I have created this code (with the help of Reimeus). How would I achieve to instead of replace every value in the array with true to replace only one pre determined (by z for example) and this always being a value on the top column of the 2d array. Furthermore I would like to how I should start to get instead of the output being true and false it being x for true and y for false but still keeping the array an boolean
import java.util.*;
class Main {
public static void main(String[] args) {
int x;
int y;
Scanner scanner;
scanner = new Scanner(System.in);
x = scanner.nextInt();
y = scanner.nextInt();
boolean[][] cells = new boolean[x][y];
for (int i = 0; i < cells.length; i++) {
Arrays.fill(cells[i], true);
System.out.println(Arrays.toString(cells[i]));
}
}
}
Use Arrays.toString to display the array content, otherwise the Object#toString representation of the Object arrays will be displayed
System.out.println(Arrays.toString(cells[i]));
Aside from Reimeus answer:
What would I need to do if I would want to make only 1 piece of the array true and decide where this true should go in the same way as I decide the length of the array.
Using fact that boolean arrays are by default filled with false values you just need to read once index of element that should be set to true just like you did with lengths
boolean[][] cells = new boolean[x][y];
int trueX = scanner.nextInt();
int trueY = scanner.nextInt();
cells[trueX][trueY] = true;
also don't forget to remove Arrays.fill(cells[i], true);
Secondly is there a way in which I could replace the true statement with "*" and the false statement with "-"
You can create second loop that will iterate over elements of row and if it its value is true print * if not - like in this code:
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
if (cells[i][j])
System.out.print("* ");
else
System.out.print("- ");
}
System.out.println();
}
or just replace "true" string from result of Arrays.toString() with * and "false" with "-"
for (int i = 0; i < cells.length; i++) {
System.out.println(Arrays.toString(cells[i]).replace("true", "*")
.replace("false", "-"));
}

How to delete the duplicate in a 2D array in java?

I'm trying to generate a Sudoku board via a 2D array: board[5][5]. The Sudoku board should only contain unique vowels. However, I have only made unique vowels appear in a row. For the columns, they still seem to have duplicates. How am I suppose to generate a column with no duplicates using the code I have so far?
Here's the code I have for generating unique letters in a row:
String [] vowels = {"A","E","I","O","U"};
String [][] board = new String [vowels.length][5];
public Actions(){
int rows = 5;
for(int row = 0;row<rows;row++){
ArrayList<String> tempVowels = new ArrayList<String>(Arrays.asList(vowels));
int numVowPerLine = (int)Math.floor(Math.random()*4);
for(int j = 0;j<numVowPerLine;j++){
do{
int pos = (int)Math.floor(Math.random()*5);
if(board[row][pos] == null){
int temp = (int)Math.floor(Math.random()*tempVowels.size());
board[row][pos] = tempVowels.get(temp);
tempVowels.remove(temp);
break;
}
}while(true);
}
}
Credits to: L7ColWinters
This is related to a rather well known problem, called the Rooks Problem.
Might I suggest a simpler loop?
EDIT: After reading comments, I see that the problem needs to be applied to each vowel. In my opinion, this is more readable:
java.util.Random random = new Random();
boolean[] r_occupied;
boolean[] c_occupied;
for (i = 0; i < vowels.length; i++)
{
// Clear the 'occupied' information
r_occupied = new boolean[5];
c_occupied = new boolean[5];
// we will put vowel[i] 'count' times into the 'board'
count = random.nextInt(5);
for (j = 0; j < count; j++)
{
// generate a random row
row = random.nextInt(5);
// if it is already occupied, select the next one
while (r_occupied[row])
row = (row + 1) % 5;
// generate a random column
col = random.nextInt(5);
// if it is already occupied, select the next one
while (c_occupied[col])
col = (col + 1) % 5;
/* put the vowel at board[row][col] */
r_occupied[row] = true;
c_occupied[col] = true;
board[row][col] = vowel[i];
}
}
Note: It will overwrite some vowels, but this should be OK.
If the content of first column / first row is A and you are on the first column / second row, you could use a truncated array, i.e. String [] availableVowels = {"E","I","O","U"};, to select from. If you pick O, then when you are on first column / thrid row, you would choose from String [] availableVowels = {"E","I","U"};. etc.
Before adding an additional vowel character in a row check if it
already contains this vowel and with continue you can pass to the
other vowel
You can also do the same thing for the columns with just switching
it
before this:
board[row][pos] = tempVowels.get(temp);
Write this:
boolean b = false;
for(int j = 0;j<columnLength; j++){
if(board[row][j] == tempVowels.get(temp))
b= true;
if(b == true)
{
b = false;
continue;
}
board[row][pos] = tempVowels.get(temp);
}

Categories