I am trying to add values into a 2d array from a text file. I cannot figure out how to convert the input file to teacher's array format. The file contains a first line that goes into an array that represents vertices. That part works fine. Every line after the first line contains numbers for the adjacency matrix. These numbers are read in but for some reason the slots in the matrix are not being filled. I need to use those numbers to fill a double array that would be the same as using this statement:
int[][] edges = {
{0,1}, {0,2},
{1,0},{1,2},
{2,0},{2,1},{2,3},{2,4},{2,6},
{3,2},{3,4},{3,5},
{4,2},{4,3},
{5,3},{5,6},
{6,2},{6,5},{6,7},
{7,6}
I have to read input from a txt file. The names represent the names of the nodes or vertices in my graph. The numbers represent the positions of the vertices in an adjacency matrix. For example the first line represents row o which maps to node john, and it means that john is connected by an edge to node 1 and 2 which are peter and mary. The numbers should map the same way as the array creation above. Here is what the file looks like :
john;peter;mary;susan;george;debbie;tom;bill;
0 1 2
1 0 2
2 0 1 3 4 6
3 2 4 5
4 2 3
5 3 6
6 2 5 7
7 6
And here is my code :
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class TestSocialGraph {
public static void main(String args[]){
String verts;
int[][] edges;
int[] intPasser;
File input = new File("GraphInput.txt");
String[] names;
try {
Scanner reader = new Scanner(input);
verts = reader.next();
names = verts.split(";");
edges = new int[names.length][names.length];
while (reader.hasNextLine()){
int b = 0;
int count = 0;
String passer = reader.nextLine();
// System.out.println(passer);
String[] temp = passer.split(" ");
intPasser = new int[temp.length];
for(int i = 1; i< temp.length; i++){
System.out.println(temp[i]);
intPasser[b] = Integer.parseInt(temp[i]);
b++;
}
System.out.println(intPasser[0]);
for(int i = 0; i< intPasser.length; i++){
edges[count][intPasser[i]] = 1;
}
count++;
}
} catch (FileNotFoundException e) {
System.out.println("File not found. Please place appropriate file and restart program");
System.exit(1);
}
}
}
It looks like you're trying to make an adjacency matrix...
I.e. The first line in your file says
0 1 2
So, this would mean node 0 is connected to node 1 & node 2. It matches with what your teacher has given also:
{0,1}, {0,2},
So, in the final 2D array edges, it should be represented like so (1s in the indexes to which node 0 is connected to):
edges[0] = {0, 1, 1, 0, 0, 0, 0, 0};
Dici's response is absolutely correct in this matter - it's the count variable's location that is creating a problem. Place int count = 0; outside the while loop, and use readLine() instead of read(), and you should get an adjacency matrix representation of that data.
The only problem is that the teacher's representation & the one you're trying to produce here are different. So, consequently, the later logic which processes these inputs will also vary. One program will run with what your teacher has provided, but won't run with the matrices you've created.
---------------------------EDIT---------------------------
In response to the comment, IMO, you'll need to go through the file twice - first to get the number of edges (in this case 20), then to fill your edges array with the actual values.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class TestSocialGraph {
public static void main(String args[]) {
int[][] edges;
File input = new File("GraphInput.txt");
try {
Scanner reader = new Scanner(input);
reader.nextLine();// Skips the first line (nameList)
int count = 0;
// Count the total number of 2 element arrays
while (reader.hasNextLine()) {
String passer = reader.nextLine();
count += passer.split(" ").length - 1;
}
reader.close();
edges = new int[count][];
int i = 0;
reader = new Scanner(input);
reader.nextLine();// Skips the first line (nameList)
while (reader.hasNextLine()) {
String passer = reader.nextLine();
String[] split = passer.split(" ");
for (int j = 1; j < split.length; j++) {
edges[i + j - 1] = new int[2];
edges[i + j - 1][0] = Integer.parseInt(split[0]);
edges[i + j - 1][1] = Integer.parseInt(split[j]);
}
i += split.length - 1;
}
reader.close();
print(edges);
} catch (FileNotFoundException e) {
System.out.println(e);
}
}
private static void print(int[][] e) {
for (int i = 0; i < e.length; i++) {
for (int j = 0; j < e[i].length; j++)
System.out.print(e[i][j] + " ");
System.out.println();
}
}
}
I hope the code isn't too obscure/unreadable.
There are a lot of things to correct in your code.
verts = reader.next(); should be verts = reader.nextLine();.
in your question edges is a 20 x 2 matrix whereas in your code it is a 8 x 8 square matrix. The number of edges in your file does not seem to depend of the number of names in the first line, so why instantiating the array of edges like this ?
variable b is useless, you can replace it with i in the loop
variable count is never incremented (or at least the incremented value is never used) since it is reinitialized at each turn of the loop. That is the reason why you never fill certain lines.
your two loops could be merged into a unic one, without using a temporary array
Where does you data come from? I would avoid writing/maintaining a parser yourself. This is a waste of time. Did you think about using JSON? Your data (in the Java-code version) looks exactly like that.
When you can turn your data into
{
"vertices" : ["john","peter","mary","susan","george","debbie","tom","bill"],
"edges" : [[0,1], [0,2], ...]
}
you can use a standard JSON parser to read into a document model and directly start using the data.
This is an example of how to work with JSON data:
http://www.mkyong.com/java/json-simple-example-read-and-write-json/
Related
I am trying to split a string with " "(space) and assigning each value on row to each respective array.
The input file contains:
4
2 2
1 3
4 7
3 4
The first line of the file has a single integer value N which is number of jobs.
The next N lines will represent a job, each with 2 values.
How do I start reading from second line from a Input file?
I want to split from Second line and assign it to 2D array. So if (2,2) is there on second line, then 2 should be assigned to array[0][0] and the other 2 to array[0][1]. For next line 1 should be assigned to array[1][0] and 3 should be assigned to array[1][1].
int num = scan.nextInt(); // taking number of jobs from first line
int[][] array = new int[num][num];
while (scan.hasNext()) //It reads till file has next line
{
String str = scan.nextLine();
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
array[i][j] = scan.nextInt();
}
}
}
Had done till here, couldn't figure out further.
int[][] array = new int[num][num];
Wrong dimensions of the array, for N = 4 you create array of 4 * 4, not 4 * 2.
Since the number of columns is fixed in your case, you should create array as new int[num][2] and update reading of the data accordingly.
String str = scan.nextLine();
for (int i = 0; i < num; i++) {
for (int j = 0; j < num; j++) {
array[i][j] = scan.nextInt();
}
}
Reading a line just to skip it may be redundant if you use Scanner to read the integer numbers using nextInt. So actually you do NOT need to read the data line by line, then split each line into String parts, and convert each part into a number because Scanner class takes care of it.
Also, the innermost loop tries to read N numbers per array row, while it's better to refer actual length of the array in the row.
Thus, it should be ok just to read the data according to the task using Scanner only:
int num = scan.nextInt(); // taking number of jobs from the first line
// preparing array of N rows and 2 columns
int[][] array = new int[num][2];
for (int i = 0; i < num; i++) {
for (int j = 0; j < array[i].length; j++) { // reading 2 ints per row
array[i][j] = scan.nextInt();
}
}
You can make it a lot easier by just ignoring the first line and letting Java do the hard work:
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
import java.util.Arrays;
public class FileToArray {
public static void main(String[] args) {
try {
try (Stream<String> stream = Files.lines(Path.of("arr.txt"))) {
String[][] nums = stream.skip(1).map(s -> s.split(" ")).toArray(String[][]::new);
System.out.println(Arrays.deepToString(nums));
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
Output
For each test case, print a single line containing one integer ― the desired number of pairs.
Example Input
2
3
2 4 2
3
0 2 3
Example Output
1
0
My solution looks like:
class Codechef {
public static void main (String[] args) throws java.lang.Exception {
ArrayList<Integer> resultList = new ArrayList<Integer>();
Scanner scanner = new Scanner(System.in);
int T;
T = scanner.nextInt();
for(int i = 0; i < T; i++) {
int N;
N = scanner.nextInt();
int A[] = new int[N];
for(int j = 0; j < N; j++) {
A[j] = scanner.nextInt();
}
quick_sort(A, 0, N-1);
int pos = 0, pairs = 0;
while(pos < A.length - 1) {
if(A[pos] == A[pos + 1]) {
pos += 2;
pairs += 1;
} else {
++pos;
}
}
resultList.add(pairs);
}
for(int pairCount : resultList) {
System.out.println(pairCount);
}
scanner.close();
}
}
It successfully runs the example test cases but fails on submission, My question is, if the input is something like 1 1 2 2 1, then what should be the answer, 3? as there are 2 pairs of 1, and 1 of 2's.
Also, what will be the suggested data structure to be used for this purpose, Java with primitive data types is taking too much longer to execute it with 40,000 input values. What's wrong with my solution
To answer your first question, I'd say yes that each pair of 1's would count separately so you'd get 3.
I think your code is failing since you're only counting touching pairs after you sort.
For example,
1 1 1, you find the first pair at index 0/1, but then advance pos += 2.This means you're missing the two other pairs of 1's.
Your solution seems to be O(nlogn) because of sorting but I can think of a O(n) solution.
int[] backing = new int [10];
for (int j = 0; j < N; j++) {
int x = scanner.nextInt();
backing[x]++;
}
//At this point, you have a backing array with the frequency of each integer
You'll want something similar to this to calculate the number of pairs. It's the frequency of each integer choose 2, since you want to choose each occurrence of a pair.
So for example if you know you have 5 1's, then you'll compute:
5!/(2!*3!) = 10
I am able to solve the problem for those test cases where there is only 1 string per row.But i fail if there are multiple strings in a single row.
For example:
Test Case Type 1:
Big matrix:
7283455864
6731158619
8988242643
3830589324
2229505813
5633845374
6473530293
7053106601
0834282956
4607924137
Small Matrix:
9505
3845
3530
I pass these kinds of test cases as 9505 occurs at most 1 time inside Big Matrix.
Test Case Type:2
Big Matrix:
7652157548860692421022503
9283597467877865303553675
4160389485250089289309493
2583470721457150497569300
3220130778636571709490905
3588873017660047694725749
9288991387848870159567061
4840101673383478700737237
8430916536880190158229898
8986106490042260460547150
2591460395957631878779378
1816190871689680423501920
0704047294563387014281341
8544774664056811258209321
9609294756392563447060526
0170173859593369054590795
6088985673796975810221577
7738800757919472437622349
5474120045253009653348388
3930491401877849249410013
1486477041403746396925337
2955579022827592919878713
2625547961868100985291514
3673299809851325174555652
4533398973801647859680907
Small Matrix:
5250
1457
8636
7660
7848
I fail these kinds of test cases where 5250(or any other row in small matrix) occurs more than once inside same row of bigger matrix:
Below is the code i have written:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
HashMap<Integer,Integer> rowCol=new HashMap();
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
//bigger array
int R = in.nextInt();
int C = in.nextInt();
String G[] = new String[R];
for(int G_i=0; G_i < R; G_i++){
G[G_i] = in.next();
}
//smaller array
int r = in.nextInt();
int c = in.nextInt();
String P[] = new String[r];
for(int P_i=0; P_i < r; P_i++){
P[P_i] = in.next();
}
for(int i = 0;i<R-r;i++)//obvious
{
for(int j = 0; j<r;j++ )//obvious
{
//if string found put in map(row at which found,column at whch found)
if(G[i].indexOf(P[j])>=0)//string found
{
rowCol.put(i,G[i].indexOf(P[j]));
}
}
}
//now check if rows are consecutive(1,2,3) and columns are equal(1,1,1)
HashSet<Integer> mc = new HashSet<Integer>(rowCol.values());//if size==1 then same column
ArrayList<Integer> mr = new ArrayList<Integer>(rowCol.keySet());
int count = 0;
for(int m = 0 ;m<mr.size()-1;m++)//checking if keys are consecutive
{
if(mr.get(m)+1==mr.get(m+1))
{
count++;//how many values are same ,hw mny strings found at same index
}
}
//System.out.println(count+"+++++"+(mr.size()-1));
//System.out.println( rowCol.values().size()+"==="+r);
if(mc.size()==1 && count==(mr.size()-1) && rowCol.keySet().size()==r)//all column same && all rows are consecutive &&
{
System.out.println("YES");
}
else
{
System.out.println("NO");
}
}
}
}
Your logic is faulty.
for(int i = 0;i<R-r;i++)//obvious
{
for(int j = 0; j<r;j++ )//obvious
{
//if string found put in map(row at which found,column at whch found)
if(G[i].indexOf(P[j])>=0)//string found
{
rowCol.put(i,G[i].indexOf(P[j]));
}
}
}
This goes through all the lines in G, and all the lines of P. If that line of P exists in that line of G, it will be placed in the map.
But first, it only tells you that some line from P is in that line of G, it doesn't tell you which line. This will mean it also fails when you are looking for a small matrix which is just like an existing matrix but different order of lines.
Second, if there is more than one line of the small matrix in the line of G, it will keep the index of the lower line from P. That is, if you have both 5250 and 7660 in the same line in G, it will keep just the index of the 7660 and ignore the 5250.
ArrayList<Integer> mr = new ArrayList<Integer>(rowCol.keySet());
You are using mr to check for consecutive line, but you are filling it with the key set from a HashMap. This means that the order is not guaranteed - you could get the line numbers in the order 5,3,1,2,4 or whatever.
You should write your program with different logic. Don't try to collect all the locations of all the lines. Find the location of the first line of P, and immediately check if the rest are in place. Say you found the first line of P in line 30 at index 15. Then check if line 2 is in line 31 at index 15, and if line 3 is in line 32 at index 15, and so on.
If all matched, print "YES", and return from the method. Do not continue the loop. But if not all matched, keep looking for P[0].
Note that there may be more than one occurrence of P[0] in the same line in G. So if matching failed, continue to search in the same line of G until no more occurrences of P[0] occur, and only then move to the next line of G.
If you didn't find any matches, then at the end of the loop you can print "NO".
I have an input text file of thousands of lines of words, where I would like write to the output file, where I reverse the order of every 10 lines. I have iterated over the entire text file, and stored it in an ArrayList<String> array and I am now trying to figure out how I can reverse the order of every 10 lines in the entire ArrayList.
so for example the output should be like this: Line : 10, 9, 8, 7 ...... 1, 20, 19, 18, 17.....11, 30, 29, 28, 27.....21 and so on until I have done this for the entire text file (Stored in the ArrayList). Below is the portion of code I have been using to try and reverse the lines as stated.
for(int i = array.size()-1; i >= array.size()-10; i--){
array.add(array.get(i));
}
for (String text : array) {
w.println(text);
}
}
What I have so far, reads and reverses only the last 10 lines of the input file and writes it to the output file. I have been having trouble figuring out a way to iteratively achieve this type of pattern throughout the entire data set, making sure that I do not hit an index out of bounds error.
Use a simple streaming approach. This is basically the current solution applied every ten lines instead of once at the end.
Read ten lines in.
Reverse these lines1.
Write the ten reversed lines out.
Repeat until the entire file is processed.
The only edge case is doing something appropriate at the end when the file isn't a multiple of 10 lines.
This same streaming approach can be used to create a new each-10 reversed list. It only 'becomes complicated' when trying to mutating the original list.
1 Steps 2 and 3 can be combined by iterating the list of ten lines backward when writing to the output.
Two approaches:
If it is already in memory, in an ArrayList, simply update that list.
If not already in memory, process 10 lines at a time.
This allows infinitely large data to be processed without running out of memory.
Option 1.
List<String> list = new ArrayList<>();
// code filling list
for (int i = 0; i < list.size(); i += 10) {
int endOfBlock = Math.min(i + 10, list.size());
for (int j = i, k = endOfBlock - 1; j < k; j++, k--) {
String temp = list.get(j);
list.set(j, list.get(k));
list.set(k, temp);
}
}
Option 2.
try (BufferedReader in = new BufferedReader(new FileReader(inFile)),
PrintWriter out = new PrintWriter(new FileWriter(outFile))) {
String[] buf = new String[10];
int len = 0;
for (String line; (line = in.readLine()) != null; ) {
buf[len++] = line;
if (len == 10) {
while (len > 0)
out.println(buf[--len]);
}
}
while (len > 0)
out.println(buf[--len]);
}
Try this
for (int i = 0, size = array.size(); i < size; i += 10)
for (int from = i, to = Math.min(i + 10, size); from < to;)
Collections.swap(array, from++, --to);
Use a secondary counter variable and an if statement to check for bounds, such as:
while(counter<array.size()+10)
int counter = 9; //since index 9 is the 10th line
for(int i=counter; i>counter-10; i--){
if(i<array.size()){
array.add(array.get(i));
}
}
counter+=10;
}
for (String text : array){
w.println(text);
}
My only concern here is that you appear to just continue adding to the existing array rather than reordering it or adding the elements to a new array?
Hi i'm trying to submit UVa 482 problem here:
In many computer problems, it is necessary to permute data arrays.
That is, the data in an array must be re-arranged in some specified
order. One way to permute arbitrary data arrays is to specify the
permutations with an index array to point out the position of the
elements in the new array. Let x be an array that is to be permuted
and let x' be the permuted array. Then, we have the relationship
between x and x' that x'pi = xi.
Input
The input begins with a single positive integer on a line by itself
indicating the number of the cases following, each of them as
described below. This line is followed by a blank line, and there is
also a blank line between two consecutive inputs. Each input set will
contain two lines of numbers. The first line will be an index array p
containing the integers 1...n, where n is the number of integers in
the list. The numbers in the first line will have been permuted in
some fashion. The second line will contain a list numbers in floating
point format.
Output
For each test case, the output must follow the description below. The
outputs of two consecutive cases will be separated by a blank line.
The output for this program will be the list of floating point numbers
from the input set, ordered according to the permutation array from
the input file. The output numbers must be printed one per line in the
same format in which they each appeared in the input file.
Sample Input
1
3 1 2
32.0 54.7 -2
Sample Output
54.7
-2
32.0
but verdict result is wrong answer, problem itself is not complicated but i'm really stuck!!!
here is my code:
import java.util.*;
class Main {
public static void main(String args[]) {
Main problem = new Main();
problem.solve();
}
void solve() {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int counter = 0;
while (counter != n) {
ArrayList<Integer> index = new ArrayList<>();
ArrayList<String> number = new ArrayList<>();
while (in.hasNextInt())
index.add(in.nextInt());
for (int i = 0; i < index.size(); i++)
number.add(in.next());
String sortedNumber[] = new String[index.size()];
for (int i = 0; i < index.size(); i++)
sortedNumber[index.get(i) - 1] = number.get(i);
for (int i = 0; i < index.size(); i++)
System.out.println(sortedNumber[i]);
if (counter < n - 1)
System.out.println();
counter++;
}
in.close();
}
}
i tested for some limited inputs also, but i could not figure it out.
You are assuming that no floating-point number is also an integer. If it is, your program does weird things.
Try this input:
2
1 2 3
0 2.0 3.0
1 2 3
1.1 2.2 3.3
You should have read permutations line-by-line:
String line = in.nextLine();
for (String s : line.split(" ")) {
index.add(Integer.parseInt(s));
}
instead of
// fails when there's starting ints in the "floating-point" line
while (in.hasNextInt()) index.add(in.nextInt());