0

I'm very new to programming. I'm studying on my own, and the examples from the book I'm using are too easy so I'm trying to do something harder. Lotteries are one of my hobbies and I think the problem I chose will make it easier for me to learn Java.

This program calculates frequencies (how many times each number from 1 t0 70 appears in my txt file) in Keno, a type of lottery(In Keno, a draw consists of 20 numbers out of 70, instead of the widespread 6 out of 49).

I want to calculate the frequencies not for the entire txt file, but just for a section of it, for example if the file has x lines, I want just the lines between x-5 and x-10, something like this.I don't know the number of lines in my file, perhaps thousands, but it always has 20 columns.

The program works fine for the entire file, but I run into trouble when trying to work just on a section of it. I think that I should read the file into a 2d array and then I could process the lines I want. I'm having hard times transferring every line into a matrix. I've read every post regarding reading a file into a 2d array but couldn't make it work.

Below is one of the many attempts I made over more than a week

public static void main(String args[]) {

    int[][] matricea = new int [30][40];
    int x=0, y=0;

    try { 
        BufferedReader reader = new BufferedReader(
            new FileReader("C:\\keno.txt")
        ); 

        int[] numbers = new int[72];  //each keno draw has 70 numbers

        for (int i = 0; i < 71; i++ ){ 
            numbers[i] = 0;      
        } 

        int k=0;    // k counts the lines 
        String draw; 

        while ( (draw = reader.readLine()) != null ) { 

            String[] pieces = draw.split(" +"); 
            k++;

            for (String str : pieces) {
                int str_int = Integer.parseInt(str);
                matricea[x][y] = str_int;
                System.out.print(matricea [x][y] + " ");
                y = y + 1;
            }

            x = x + 1;
            System.out.println(" "); 
        }

        for (int j = 1; j <= 20; j++) { 
            int drawnNumber = Integer.parseInt(pieces[j]); 
            numbers[drawnNumber]++; 
        } 

        System.out.println(" nr. of lines is  " + k);
        reader.close(); 

        for (int i = 0; i < 71; i++) { 
            System.out.println(i + ": " + numbers[i]); 
        } 

    } catch (Exception e) { 
        System.out.println("There was a problem opening and processing the file."); 
    } 

}
greuceanu
  • 13
  • 6
  • 1
    If you want help you should at least take time to format your question nicely instead of a wall of text. You should also indent your code properly. As it is its extremely hard to read and will just get passed over by most people – user1231232141214124 Apr 15 '16 at 20:51
  • How is the format of the file? – raven Apr 15 '16 at 21:47
  • Sorry. This is my first post. I'll make the code look nicer. The file is txt. – greuceanu Apr 15 '16 at 21:56
  • In the United States, one Keno game is a draw of 20 numbers out of **80**. The player can select 1 to 7 numbers that he hopes are included in the 20 numbers drawn. The odds of one number hitting is 50%. The odds of the other multi number selections are less than 50%. Please describe your Keno game more fully. – Gilbert Le Blanc Apr 15 '16 at 22:18
  • In Ontario, Canada, the draw is 20 out of 70. I don't want to calculate odds or other things. Just the frequencies on a certain section of a file containing the numbers from previous drawns. – greuceanu Apr 15 '16 at 22:32

1 Answers1

1

Formatting and improving current code

I'll show how to solve your problem, but first I would like to point out a few things in your code that could be improved by some formatting, or that perhaps are unnecessary.

Just to help you improve your coding skills, readability is very important! :)

And don't forget, consistency is key! If you like one style better than the more common style, or the preferred style, that's fine as long as you use it throughout your coding. Don't switch between two styles.

If you don't care to read these comments, you can find the solution at the bottom of my answer. Just note that your original code will be different in my solution because I have formatted it to be most readable for me.


Spacing in variable declarations

Original code

int[][] matricea = new int [30][40];
int x=0, y=0;

Spacing modified

int[][] matricea = new int[30][40];
int x = 0, y = 0;

Notice the space removed between int and [30][40], and the space added between the variables and the initialization, i.e. - x=0 => x = 0.


Initializing an int array to contain all 0's

Original code

int[] numbers = new int[72];  //each keno draw has 70 numbers

for (int i = 0; i < 71; i++ ){ 
    numbers[i] = 0;      
} 

Same as

int[] numbers = new int[72];  //each keno draw has 70 numbers

You don't have to set each value to 0, Java will do that for you. In fact, Java has default values, or null values, for all types. Thanks to Debosmit Ray!

I won't go into the exceptions to this case, or when or why or how, you can read about that in this post, and pay close attention to Aniket Thakur's answer.

But why do you have an array of size 72, if there are only 70 possibilities?


Choosing variable names

Original code

int k=0;     // k counts the lines

Same as

int numLines = 0;

You should always make your variables names something meaningful to their purpose. If you ever have to put a comment like k counts the lines to describe a variable's purpose, consider if a better name would work instead.


Functionalizing code

Original code

 while ( (draw = reader.readLine()) != null ) { 

      String[] pieces = draw.split(" +"); 
      k++;
                    
      for (String str : pieces) {
           int str_int = Integer.parseInt(str);
           matricea[x][y] = str_int;
           System.out.print(matricea [x][y] + " ");
           y = y + 1;
      }
                
      x = x + 1;
      System.out.println(" "); 
 }

Same as

while ( (draw = reader.readLine()) != null ) { 
    processLine(draw);
}

Of course, you'll have to make the method processLine(String line), but that won't be hard. It's just taking what you have and moving it to a separate method.

The original code's while loop is very busy and messy, but with the latter option makes the purpose clear, and the code clean.

Of course each situation is different, and you might find that only removing part of the code into a method would be a better solution. Just play around and see what makes sense.


Error!

Original code

for (int j = 1; j <= 20; j++) { 
    int drawnNumber = Integer.parseInt(pieces[j]); 
    numbers[drawnNumber]++; 
} 

This code should not work, since pieces is declared in the while loop above it, and is local to that above loop. This for loop is outside the scope of where pieces exists.

I'll tell you how to fix it, but I'm not sure what the code is supposed to be doing. Just let me know what its purpose is, and I'll provide you with a solution.


After formatting!

This is what the code may look like after applying my above comments. I have added comments to parts that I have changed.

public static void main(String args[]) {

    try { 
        doKenoStuff();
    } catch(IOException e) {
        System.out.println("There was a problem opening and processing the file.");
    }
    
}

public static void doKenoStuff() throws IOException {
    BufferedReader reader = new BufferedReader(
            new FileReader("C:\\keno.txt")
    ); 
    
    int[][] matricea = new int[30][40];
    int[] numbers = new int[72];  //each keno draw has 70 numbers
    
    // We can clean up our loop condition by removing
    // the assignment (draw = reader.readLine) from it.
    // Just make sure draw doesn't begin as null.
    String draw = "";
    int row;
    
    for(row = 0; draw != null; row++) {
        draw = reader.readLine();
        
        // We read a line from the file, then send it
        // to extractLineData which will collect the info
        // from each column, and update matricea and numbers
        extractLineData(draw, row, matricea, numbers);
    }
    
    System.out.println("Number of lines: " + row);
    System.out.println("Each number's drawing stats:");
    
    for (int i = 0; i < 71; i++) { 
        System.out.println(i + ": " + numbers[i]); 
    } 
    
    reader.close(); 
    
}

public static void extractLineData(String line, int row, int[][] matrix, int[] numbers) {
    String linePieces = line.split(" +");
    
    for(int column = 0; column < linePieces.length; column++) {
        int number = Integer.parseInt(linePieces[column]);
        matrix[row][column] = number;
        numbers[number]++;
    }
}

Solution

Note: I am not perfect, and my code is not either. I'm not trying to say that what I have suggested is in any way the only way to do this. It could definitely be improved, but it is a start. You should take my solution and see how you can improve it yourself.
What can you find that you could code in a cleaner, or faster, or better way?

So, how do we fix the problem?

We have a method that reads from the start of a file, to the end of it, and it logs the data it finds inside matricea.

A quick and easy solution is to simply make that method take in two parameters, a starting line number, and an ending line number.

public static void doKenoStuff(int start, int end) throws IOException {

Then we simply make a loop to skip over the starting lines! It's that easy!!!

for(int i = 0; i < start - 1; i++) {
    reader.readLine();
}

Don't forget that we may not need the big 30 row matricea to be 30 rows anymore. We can shrink that down to end - start + 1. That way, if a user wants to read from line 45 to line 45, we only need 45 - 45 + 1 = 1 row in matricea.

int[][] matricea = new int[end - start + 1][40];

And the very last thing we need to add is a condition in our line reading loop, that prevents us from going past the ending line.

for(row = 0; draw != null, row <= end; row++) {

And there you have it. Simple as that!


Complete solution

public static void main(String args[]) {
    int start = 7, end = 18;

    try { 
        doKenoStuff(start, end);
    } catch(IOException e) {
        System.out.println("There was a problem opening and processing the file.");
    }
}

public static void doKenoStuff(int start, int end) throws IOException {
    BufferedReader reader = new BufferedReader(
            new FileReader("C:\\keno.txt")
    ); 
    
    int[][] matricea = new int[end - start + 1][40];
    int[] numbers = new int[72];  //each keno draw has 70 numbers
    
    for(int i = 0; i < start - 1; i++) {
        reader.readLine();
    }
    
    String draw = "";
    int row;
    
    for(row = 0; draw != null, row <= end; row++) {
        draw = reader.readLine();
        extractLineData(draw, row, matricea, numbers);
    }
    
    System.out.println("Number of lines: " + row);
    System.out.println("Each number's drawing stats:");
    
    for (int i = 0; i < 71; i++) { 
        System.out.println(i + ": " + numbers[i]); 
    } 
    
    reader.close(); 
}

public static void extractLineData(String line, int row, int[][] matrix, int[] numbers) {
    String linePieces = line.split(" +");
    
    for(int column = 0; column < linePieces.length; column++) {
        try {
            int number = Integer.parseInt(linePieces[column]);
            matrix[row][column] = number;
            numbers[number]++;
        } catch (NumberFormatException) {
            // You don't have to do anything in this block, but
            // you can print out what input gave the exception if you want.
            System.out.println("Bad input: \"" + linePieces[column] + "\"");
        }
    }
}
        
Community
  • 1
  • 1
Matt C
  • 4,470
  • 5
  • 26
  • 44
  • To any reader, I accidently posted my answer before I finished making it. I'm editing in the solution right now. – Matt C Apr 15 '16 at 23:01
  • j is the column counter. then every number on that line is put in the array numbers. Sometimes in the file there are things after column 20 and I don't want to have them in the file – greuceanu Apr 15 '16 at 23:29
  • for some reason the program didn't work with 70, or 71 , it only liked 72 – greuceanu Apr 15 '16 at 23:30
  • before this part of the program for (String str : pieces) { int str_int = Integer.parseInt(str); matricea[x][y] = str_int; System.out.print(matricea [x][y] + " "); y = y + 1; } x = x + 1; System.out.println(" "); } – greuceanu Apr 15 '16 at 23:32
  • Without this part : for (String str : pieces) { int str_int = Integer.parseInt(str); matricea[x][y] = str_int; System.out.print(matricea [x][y] + " "); y = y + 1; } x = x + 1; System.out.println(" "); } the program was working fine, but it was calculating frequencies for the entire file. I wrote this piece of code to try to create a 2d array and to put in it the file so that I can process whichever lines I want. It just that it doesn't work – greuceanu Apr 15 '16 at 23:38
  • 1
    Thanks for the suggestions above – greuceanu Apr 15 '16 at 23:40
  • 2
    `Initializing an int array to contain all 0's` not needed. int primitive has a null value of 0. might want to add that to the section – Debosmit Ray Apr 15 '16 at 23:57
  • @DebosmitRay Thanks for the suggestion, added in. – Matt C Apr 16 '16 at 00:06
  • @greuceanu I've added quite a bit since you might have last seen my answer. Maybe what I have added will fix the issue. Just let me know. Thanks! – Matt C Apr 16 '16 at 00:07
  • 1
    the library is closing, I'll post again when I get home. So far my Netbeans gives me some errors, and I'm not familiar at all with the code you wrote. There might be some comas missing or something. I'll keep you posted. – greuceanu Apr 16 '16 at 00:25
  • @greuceanu Sounds good. If you need more help, just comment again on this and be sure to `@` me. – Matt C Apr 16 '16 at 00:32
  • @MatthewCliatt made some small changes, but it Netbeans still gives me these errors: Exception in thread "main" java.lang.NumberFormatException: For input string: " ". Or : at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:592). – greuceanu Apr 19 '16 at 22:36
  • @greuceanu For what input? – Matt C Apr 19 '16 at 22:48
  • @MatthewCliatt 1 2 4 6 9 13 15 16 21 28 34 37 41 48 50 52 53 54 57 68 6 7 10 17 23 24 27 28 31 39 42 43 46 48 50 55 60 61 67 70 2 3 5 7 11 14 15 20 28 45 46 47 48 52 56 61 62 63 66 70 4 5 7 11 13 15 19 23 24 27 28 35 38 40 48 50 57 58 64 66 3 8 20 26 27 32 36 38 39 43 45 47 50 53 54 56 59 61 67 68 1 3 5 7 15 19 26 30 31 36 41 44 48 49 56 58 59 60 61 65 1 2 4 6 9 13 15 16 21 28 34 37 41 48 50 52 53 54 57 68 6 7 10 17 23 24 27 28 31 39 42 43 46 48 50 55 60 61 67 70 2 3 5 7 11 14 15 20 28 45 46 47 48 52 56 61 62 63 66 70 4 5 7 11 13 15 19 23 24 27 28 35 38 40 48 50 57 58 64 66 – greuceanu Apr 19 '16 at 23:03
  • @MatthewCliatt. this is not my file. When I pasted it in the box it was ok. After I hit enter the site messed it up. It's a 2d array with 10 lines and 20 columns. How can I post it properly? – greuceanu Apr 19 '16 at 23:07
  • Quick question, why did you first split the string with `" +"` instead of `" "`? I assumed because of the way your text file was formatted. But this text file doesn't have any `+`'s. Change the `split` method to `split(" ");` in the `extractLineData` method. So the line should look like this now: `String linePieces = line.split(" ");` – Matt C Apr 19 '16 at 23:41
  • @MatthewCliatt (" ") its just for space. (" +") is for space and a few more things, I've read that (" +") it's better. I used both in this code, I get the same errors – greuceanu Apr 20 '16 at 00:00
  • @greuceanu Gotcha. I've added in a try catch block into the bottom of my answer, in the "complete solution" section. This will make sure that no errors occur while reading the file. If they do, you can print out what caused them, or just continue on. I think its just a small bug with Scanner and the buffer, but we should have a try catch anyway, in case there are words in the file from typos or anything else. Let me know if that works. – Matt C Apr 20 '16 at 00:13
  • @MatthewCliatt Thanks. I'll let you know – greuceanu Apr 20 '16 at 00:21
  • @MatthewCliatt netbeans gave me lots of errors, made some small changes, ran the program and now it says bad input and some other messages about main, extractLineData and doKenoStuff – greuceanu Apr 20 '16 at 23:22
  • @greuceanu I can help you troubleshoot these small errors. But I think it's time we should move from this post. If you don't mind either accepting my answer or at least upvoting it, I would very much appreciate that, of course only if it answered the question you had. But us commenting back and forth on here won't solve much from now on. Let's communicate either via the chat on here, or via email. My email is `mtcliatt@valdosta.edu`. Just email me the errors and I'll help you figure them out. – Matt C Apr 21 '16 at 18:41
  • @MatthewCliatt ok, let's move it to chat – greuceanu Apr 22 '16 at 22:34