Using a tally array to keep counts of another array - java

I am writing a program that reads through a .txt file of weather data, and among other things, keep count of various weather patterns for each day of the year.
The .txt file has 365 lines of various values (one line of values for each day of the year). Each line houses the high temp, low temp, and Weather status (formatted as a String of six 1's and 0's, with a 1 indicating that Fog/Rain/Snow/Hail/Thunder/Tornado occurred on that day). For example, the String 011000, would indicate that both rain and snow occurred.
Sample weather file looks like (line breaks for spacing):
High, Low, Weather String:
45, 32.4, 100000
43.2, 35, 100001
50.2, 32.1 101101
I have completed the vast majority of the program that traces through the weather.txt file and keeps track of the yearly high and yearly low, yet am having trouble tallying the weather status for each type (6 types). I realize I don't do the best in explaining, but my goal is to keep count, for all 365 formatted String values, how many 1's for each index of the String. So in looking at the sample weather file above, my end result would be [3, 0, 1, 1, 0, 2].
In the pasted method below, I pass in a String array (I created a String array previously in the program, which houses all 365 String formatted values... [100001, 100000, 101101, ...]). In this method, I created a new tally array with 6 values. I am trying to write a loop that traces through the passed in weather array (365 values), and increases the tally array index if a 1 occurs at the said index. The final tally array would look something like [101, 31, 3, 218, 42, 101]...made up numbers for sample output.
The logic is giving me a lot of trouble. Assuming I have done my bit in explaining this, can anyone offer me advice.
Note - the class constant of NUMBER_OF_WEATHER_TYPES is set to 6.
public static int[] getWeatherCounts(String[] weather) {
int[] tally = new int[6];
for (int i = 0; i < weather.length; i++) {
for (int j = 0; j < NUMBER_OF_WEATHER_TYPES; j++) {
if (weather[j].charAt(j) == 1) {
tally[j]++;
}
return tally;
}
}
return tally;
}
Whole program for context:
import java.util.*;
import java.io.*;
public class WeatherInfo {
public static final int DAYS_PER_YEAR = 365;
public static final int NUMBER_OF_WEATHER_TYPES = 6;
public static void main (String[] args) {
String firstArgs = args[0];
Scanner input = null;
if (args.length != 1) {
System.out.println("Error"); //Look more into this!!!!
} else {
try {
input = new Scanner(new File(firstArgs));
} catch (FileNotFoundException e) {
System.out.println("Error: " + e);
System.exit(1);
}
}
String lineDiscard = input.nextLine();
double[] highs = new double[DAYS_PER_YEAR];
double[] lows = new double[DAYS_PER_YEAR];
String[] weather = new String[DAYS_PER_YEAR];
for (int i = 0; i < DAYS_PER_YEAR; i++) {
input.next();
input.next();
highs[i] = input.nextDouble();
lows[i] = input.nextDouble();
weather[i] = input.next();
}
displayWeatherStatistics(highs, lows, weather);
}
public static void displayWeatherStatistics(double[] highs, double[] lows, String[] weather) {
double highTemp = Integer.MIN_VALUE;
double lowTemp = Integer.MAX_VALUE;
// for loop for highs
for (int i = 0; i < highs.length; i++) {
if (highs[i] > highTemp) {
highTemp = highs[i];
}
}
// for loop for lows
for (int i = 0; i < lows.length; i++) {
if (lows[i] < lowTemp) {
lowTemp = lows[i];
}
}
// printouts for the low and high temps of the year...need to fix this a bit
System.out.println("Highest Temp: " + highTemp + " (F)");
System.out.println("Lowest Temp: " + lowTemp + " (F)");
System.out.println(Arrays.toString(getWeatherCounts(weather)));
}
public static int[] getWeatherCounts(String[] weather) {
int[] tally = new int[6];
for (int i = 0; i < weather.length; i++) {
for (int j = 0; j < NUMBER_OF_WEATHER_TYPES; j++) {
if (weather[i].charAt(j) == 1) {
tally[j]++;
}
return tally;
}
}
return tally;
}
}

Well, it's hard to tell without seeing your whole program. But it looks to me like
if (weather[j].charAt(j) == 1) {
tally[j]++;
}
return tally;
should be
if (weather[i].charAt(j) == '1') {
tally[j]++;
}
// omit the return tally, we don't want to do that until the end

Related

median and mode displaying -1

Hey guys I have been learning coding recently and got an assignment of finding the mean, median and mode of a number of integers in an integer array. The issue that I am facing is that my median and mode displays -1 and I'm not too sure how to fix it, my "if user inputs no, print an error statement" is also not working and I would be very grateful if someone could help me out.
This is my code:
package com.company;
import java.io.File;
import java.io.FileNotFoundException;
import static com.company.ProjectConstants.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] a = new int[MAXDATA];
int counter = 0;
boolean fileDone = false;
boolean inputOk;
String userInput;
String theDataFile;
Scanner s = new Scanner(System.in);
genProgInfo();
userInput = s.nextLine();
userInput = userInput.toLowerCase();
while (!userInput.equals("yes") && (!userInput.equals("no"))) {
System.out.println("ERROR: Please input either yes or no: ");
userInput = s.nextLine();
userInput = userInput.toLowerCase();
}
inputOk = userInput.equals("yes");
initDataStorage(a);
//do {
try {
// create file & scanner objects
System.out.println("enter one of the file names:\nData10File.txt\nData30file.txt\nData35file.txt");
theDataFile = s.next();
theDataFile = theDataFile.toLowerCase();
//fName = userInput;
File f = new File(theDataFile);
Scanner sc = new Scanner(f);
// store file data in array, a
for (int i = 0; i < MAXDATA; i++) {
if (sc.hasNext()) {
a[i] = sc.nextInt();
} else {
fileDone = true;
sc.close();
break;
}
}
// print error message if file data exceeds the range of array
if (!fileDone) {
System.out.println("\n\tCAUTION: file has additional data, consider making array larger.");
}
} catch (FileNotFoundException e) {
System.out.println(e);
e.printStackTrace();
}
//} while (inputOk);
s.close();
for (int i=0; i<MAXDATA; i++) {
if (a[i] != -1) {
counter = a[i];
}
}
System.out.println("counter: "+ counter);
displayResults(calcMean(a), calcMedian(a), calcMode(a));
}
public static void initDataStorage(int[] data) {
for (int i = 0; i < MAXDATA; i++) {
data[i] = INVALID;
}
}
public static double calcMean(int[] data) {
int counter = 0;
int mean;
int sum = 0;
for (int i = 0; i < MAXDATA; i++) {
if (data[i] != -1) {
sum += data[i];
counter++;
}
}
mean = sum / counter;
return mean;
}
public static double calcMedian(int[] data) {
int middle = data.length / 2;
if (data.length % 2 == 1) {
return data[middle];
} else {
return (data[middle -1] + data[middle]) / 2.0;
}
}
public static int calcMode(int[] data) {
int mode = 0, maxCount = 0;
for (int i = 0; i < data.length; ++i) {
int count = 0;
for (int j = 0; j < data.length; ++j) {
if (data[j] == data[i]) {
count++;
}
}
if (count > maxCount) {
maxCount = count;
mode = data[i];
}
}
return mode;
}
public static void genProgInfo() {
System.out.println("This program will calculate the mean, median, and mode of a number of integers stored in the array");
System.out.println("Would you like to continue?");
}
public static void displayResults(double mean, double median, int mode) {
System.out.println("mean: " + mean);
System.out.println("median: " + median);
System.out.println("mode: " + mode);
}
}
I'm assuming the value of INVALID is -1 based on the other code I see and your description of what it outputs. Your array is of length MAXDATA and is initially filled with value INVALID in all elements. You then fill it with n values where n may be less than MAXDATA, and in that (probably common) case, many or even most of the values in the array are the INVALID value.
Your calcMean function is correctly skipping over the -1 (INVALID?) values and not including them in the calculation. Note however that the valid values are all at the beginning of the array and once you find an invalid value, you could break out of the loop in calcMean.
But the calcMedian and calcMode functions are not accounting for the invalid values. If n is significantly less than MAXDATA, then -1 probably really is the mode. Your calcMedian function has an additional problem as well, in that the (valid) data needs to be sorted in order for the "middle" or median value to be in the middle of the array.
Bonus question for your assignment: What if -1 occurs in the input file?

Scanner input values are not all being stored

I have a scanner which reads in strings as coordinate inputs. I have to convert these strings into integers and store them in an Arraylist of coordinates but the last values I input are not being stored in the arraylist.
I have tried using the startEndLineScan.nextLine(); outside the for-loop but still no change I have also tried using a while loop instead of a for loop when storing and parsing the strings but I get the same results.
ArrayList<Integer> convertedCoords = new ArrayList<Integer>();
String samplePointsCoords[];
Scanner startEndLineScan = new Scanner(System.in);
int count = 1;
while (startEndLineScan.hasNextLine()) {
startEndPointsInputs = startEndLineScan.nextLine();
samplePointsCoords = startEndPointsInputs.split(",");
if (count < 2) {
for (int i = 0; i < samplePointsCoords.length; ++i) {
convertedCoords.add(Integer.parseInt(samplePointsCoords[i]));
}
count++;
} else {
break;
}
}
System.out.print("Points: " + convertedCoords)
Input:
1,2
3,4
Expected results:
Points: [1,2,3,4]
Actual Results
Points: [1,2]
ArrayList<Integer> convertedCoords = new ArrayList<Integer>();
String samplePointsCoords[];
Scanner startEndLineScan = new Scanner(System.in);
int count;
while (startEndLineScan.hasNextLine()) {
count = 1;
startEndPointsInputs = startEndLineScan.nextLine();
samplePointsCoords = startEndPointsInputs.split(",");
if (count < 2) {
for (int i = 0; i < samplePointsCoords.length; ++i) {
convertedCoords.add(Integer.parseInt(samplePointsCoords[i]));
}
count++;
} else {
break;
}
}
System.out.print("Points: " + convertedCoords)
Notice int count; is declared and reinitialized at the start of every loop
This will fix your code but you should really try to understand what you are writing! cheers.

How can I check multiple duplicates in one array? [ReadyJava]

This program receives 100 inputs and then outputs the lowest value. I need help checking all duplicated values inputted.
Example with 5 inputs:
5,1,1,5,4
The smallest value: 1
The amount of duplicated values: 4
import java.awt.*;
import hsa.Console;
public class ArrayNumbers
{
static Console c;
public static void main (String[] args)
{
c = new Console ();
int number[] = new int [100], i = 1, output = 0;
c.print ("Enter number #1:");
number [0] = c.readInt ();
output = number [0];
for (int count = 0 ; count < 99 ; count++)
{
c.print ("Enter number #" + (count + 2)+ ":");
number [i] = c.readInt ();
if (number [i] < output)
{
output = number [i];
}
i++;
}
c.print(output);
} // main method
} // ArrayNumbers class
It can be done by using map. Please find below code for the same:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class MinAndDuplicates {
public static void main(String[] args) {
int number, totalDupCount=0;
Scanner stdin = new Scanner(System.in);
Map<Integer, Integer> map = new HashMap<Integer,Integer>();
//Prepare map with duplicate count for each number
for (int i = 0; i < 5; i++) {
number=stdin.nextInt();
if(map.containsKey(number)){
map.put(number, ((Integer)map.get(number)+1));
}else{
map.put(number, 1);
}
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int numberCount= entry.getValue();
if (numberCount> 1) {
totalDupCount+= numberCount;
}
}
System.out.println(totalDupCount);
}
}
Hope this helps!
Below is the logic to perform your duplicate count in O(n) time and O(1) extra space.
try this
// Function to find counts of all elements present in
// arr[0..n-1]. The array elements must be range from
// 1 to n
// Traverse all array elements
int[] arr = {5,1,1,5,4};
int i = 0,n=arr.length;
int totalDupCount = 0;
while (i < n) {
// If this element is already processed,
// then nothing to do
if (arr[i] <= 0) {
i++;
continue;
}
// Find index corresponding to this element
int elementIndex = arr[i] - 1;
// If the elementIndex has an element that is not
// processed yet, then first store that element
// to arr[i] so that we don't loose anything.
if (arr[elementIndex] > 0) {
arr[i] = arr[elementIndex];
// After storing arr[elementIndex], change it
// to store initial count of 'arr[i]'
arr[elementIndex] = -1;
} else {
// If this is NOT first occurrence of arr[i],
// then increment its count.
arr[elementIndex]--;
// And initialize arr[i] as 0 means the element
// 'i+1' is not seen so far
arr[i] = 0;
i++;
}
}
System.out.println("Below are counts of all elements");
for (int j = 0; j < n; j++){
if(Math.abs(arr[j]) >= 2){
System.out.println(j + 1 + "->" + Math.abs(arr[j]));
totalDupCount +=Math.abs(arr[j]);
}
}
System.out.println("Total Duplicate Count in Array is : "+totalDupCount);
}
Output
Below are counts of all elements
1->2
5->2
Total Duplicate Count in Array is : 4
(This post is slightly uglier than my first approach, but it solves the poster's question the way they'd like it to. I have decided to put it as a separate answer.)
If you want to count the number of duplicated numbers multiple times
depending on how often they show up, you can do it with a
HashMap.
The Approach
Create a HashMap to count how often each number appears.
When reading input, increment the occurrences of that number.
To find the number of "duplicates", iterate through the HashMap and sum all of the occurrences which happen more than once.
Example
import java.util.Scanner;
import java.util.Map;
import java.util.HashMap;
public class DuplicateCounter {
static int[] numbers = new int[100];
static HashMap<Integer, Integer> occurrences = new HashMap<>();
public static void main(String[] args) {
readInput();
int duplicates = countDuplicates();
System.out.printf("%d numbers appeared multiple times.\n", duplicates);
}
public static void readInput() {
Scanner stdin = new Scanner(System.in);
for (int i = 0; i < numbers.length; i++) {
int number = stdin.nextInt();
numbers[i] = number;
incrementCount(number);
}
stdin.close();
}
public static int countDuplicates() {
int duplicates = 0;
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int numOfOccurrences = entry.getValue();
if (numOfOccurrences > 1) {
duplicates += numOfOccurrences;
}
}
return duplicates;
}
public static void incrementCount(int number) {
if (occurrences.get(number) != null) {
int previous = occurrences.get(number);
occurrences.put(number, previous + 1);
} else {
occurrences.put(number, 1);
}
}
}

Convert array elements from string to an integer

I'm trying to count up the values stored in an array, here is my code:
public void printScores()
{
String sep = ":";
File inputfile = new File ("P:/SD/Assignment1/fbScores.txt");
String [] stringArr;
String line = "";
try {
Scanner filescan = new Scanner(inputfile);
while(filescan.hasNext())
{
line = filescan.nextLine();
stringArr = line.split(sep);
if(stringArr.length == 4)
{
System.out.println(stringArr[0]+"\t [" +stringArr[2]+"]\t|" + stringArr[1]+"\t["+ stringArr[3]+" ]\n");
}
else
{
throw new IllegalArgumentException("String " + line + " does not contain " + sep);
}
}
filescan.close();
}
catch (FileNotFoundException e)
{
System.out.println("problem " +e.getMessage());
}
}
public void totalGoals()
{
int count;
for (int i = 0; i<stringArr.length; i++)
{
//int num[i] = Integer.parseInt(stringArr);
}
}
}
Basically I only want to add the numbers up that are stored in [2] and [3], my totalGoals method at the bottom is where I started, but can't figure out how to change from a string to an integer, any help would be much appreciated!
UPDATE:
public void totalGoals()
{
int[] num = new int[stringArr.length];
int count = 0;
for (int i = 0; i<stringArr.length; i++)
{
num[i] = Integer.parseInt(stringArr[i]);
count = count + num[i];
System.out.println(count);
}
}
You want to parse each string individually - you seem to be trying to do the whole array
int[] num = new int[stringArr.length]; //don't forget to declare your num[] array
for (int i = 0; i<stringArr.length; i++)
{
num[i] = Integer.parseInt(stringArr[i]); // stringArr[i] instead of stringArr
}
Note what this code is actually doing when you break it out of the for loop format.
int[] num = new int[4];
num[0] = Integer.parseInt(stringArr[0]); //the for loop is starting at 0 and stopping
num[1] = Integer.parseInt(stringArr[1]); //when it hits 4
num[2] = Integer.parseInt(stringArr[2]);
num[3] = Integer.parseInt(stringArr[3]);
In truth, you only need 2 and 3.. and all you need to do is add them together. You already have a count variable you could use instead of num
So lets say you only want to loop through 2 and 3... look at the for loop
for (int i = 0; i < stringArr.length; i++)
int i = 0 //your loop is starting at 0
i < stringArr.length; //its ending when i is the array's length (should be 4 judging by your other code)
i++ // i increases by 1 at the end of each time through
So if 0 and 1 are useless, try using int i = 2
You have a count variable. Maybe it should start at 0.. and rather than setting the num variable, you could add the value to your count variable.
About your method.. By itself it should be working.
I'm also not sure which line is line 73
If it is the first line: int[] num = new int[stringArr.length]; Then either your stringArr doesn't exist (for this method) or your stringArr isn't initialized (again, for this method)
Looking at the code you've shown me, I'm guessing the problem is on that first line.
public void printScores() {
//other code
String[] stringArr;
//other code
}
public void totalGoals() {
int[] num = new int[stringArr.length];
int count = 0;
for (int i = 0; i<stringArr.length; i++)
{
num[i] = Integer.parseInt(stringArr[i]);
count = count + num[i];
System.out.println(count);
}
}
Done simply like this, you wouldn't even be able to compile. stringArr would not exist for totalGoals. The two methods are separate and cannot "see" each other's variables.
If you have your code like below - then you are declaring stringArr twice and you have two separate variables named the same thing!
{
String[] stringArr; //This is what totalGoals would be using - it is never assigned
public void printScores() {
String[] stringArr; //This one is used and assigned within printScores
//but totalGoals cannot see/use it
}
public void totalGoals() {
}
}
Use Integer.parseInt(String s) or Integer.parseInt(String s, int radix) to convert your Strings to Integers or primitive ints.
For instance:
try {
String s = "42";
int i = Integer.parseInt(s);
}
catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
You can also use Scanner.nextInt if that suits your context better.
Use integer.parseint to parse string to int
if(stringArr.length == 4)
{
for(int i=0;i<stringArr.length;i++)
{
int c = Integer.parseInt(stringArr[2])+ Integer.parseInt(stringArr[3]);
}
}

Reading in information into multiple arrays

The purpose of this program is to take information from a file about a music collection and turn it into three arrays.
>4
>141 Pure Heroine:Lorde
>171 Lights Out:Ingrid Michaelson
>270 Unorthodox Jukebox :Bruno Mars
>190 Head Or Heart:Christina Perri
In the file, the 4 stands for how long the arrays will be, the numbers are one array, the album titles another, and the artist names are the final array. The arrays for the titles and artist names are separated by the colon. While I can create the array for the numbers, what is giving me trouble is how to create the separate arrays for name and titles. I understand that I have to convert it into a sting and use the colon as a delimiter but I'm unsure as to how.
import java.util.*;
import java.io.*;
public class tunes {
public static void main(String[] args) throws FileNotFoundException {
int size; //Determines the size of the arrays
Scanner input = new Scanner(new File("music.txt"));
size = input.nextInt();
int[] time = new int[size];
for (int i = 0; i < time.length; i++) { // Creates an array for the numbers
time[i] = input.nextInt();
input.nextLine();
}
String[] artist = new String[size];
for (int i = 0; i <artist.length; i++) {
while (input.hasNextLine()){
}
}
System.out.println();
System.out.println("TOTAL TIME\t\t\t\t" + calcTotalTime(time));
System.out.println();
System.out.println();
System.out.println("LONGEST TRACK");
System.out.println("-------------");
System.out.println();
System.out.println();
System.out.println("SHORTEST TRACK");
System.out.println("--------------");
}
public static void printTable(int[] time, String[] artist, String[] title) {
System.out.println("TITLE\t\t\t" + "ARTIST\t\t\t " + "TIME");
System.out.println("-----\t\t\t" + "------\t\t\t " + "----");
for (int i = 0; i < time.length; i++) {
System.out.println(title[i] + "\t" + artist[i] + "\t" + time[i]);
}
}
public static int calcTotalTime(int[] time) {
int sum = 0;
for (int i = 0; i < time.length; i++) {
sum = sum + time[i];
}
return sum;
}
public static int findLongest(int[] time) {
int longest = 0;
for (int i = 1; i < time.length; i++) {
if (time[i] > time[longest]) {
longest = i;
}
}
return longest;
}
public static int findShortest(int[] time) {
int shortest = 0;
for (int i = 1; i < time.length; i++) {
if (time[i] < time[shortest]) {
shortest = i;
}
}
return shortest;
}
}
An example of how the output would look like would be
>Pure Heroine Lorde 141
>Lights Out Ingrid Michaelson 171
>Unorthodox Jukebox Bruno Mars 270
>Head or Heart Christina Perri 190
You can use String.split(":") on your text to split the artist/title Strings into String[] arrays.
For instance:
System.out.println(Arrays.toString("Head Or Heart:Christina Perri".split(":")));
Output
[Head Or Heart, Christina Perri]
Use the String split() method to save the pieces into a new array. The split() method takes a regular expression - see this question about how to use it. The colon is not a special character in a RegExp and therefore does not need to be escaped.
Allocate all the arrays first after reading the length of the arrays, then parse each line in one go using split to tokenize the artist-title part of the line.
size = input.nextInt();
int[] time = new int[size];
String[] artist = new String[size];
String[] title = new String[size];
for (int i = 0; i < time.length; i++) {
time[i] = input.nextInt();
String[] parts = input.next().split( ":" );
artist[i] = parts[0];
title[i] = parts[1];
}

Categories