Sets using bit strings in Java trouble - java

public class BitStringOperations3
{
public static void main (String args[])
{
Scanner in = new Scanner (System.in);
int setA = 0;
int setB = 0;
int elementsSetA = 0;
int elementsSetB = 0;
System.out.println ("How many integers are in set A?");
elementsSetA = in.nextInt ();
while (elementsSetA > 9 || elementsSetA < 0)
{
System.out.println ("This input is invalid. Please enter a number between 0 and 9 and try again.");
elementsSetA = in.nextInt();
}
System.out.println ("How many integers are in set B?");
elementsSetB = in.nextInt ();
while (elementsSetB > 9 || elementsSetB < 0)
{
System.out.println ("This input is invalid. Please enter a number between 0 and 9 and try again.");
elementsSetB = in.nextInt();
}
for (int i = 1; i <= elementsSetA; i++)
{
System.out.println ("Please enter integer number " + i + " in set A: ");
setA = add(setA, in.nextInt() );
}
for (int i = 1; i <= elementsSetB; i++)
{
System.out.println ("Please enter integer number " + i + " in set B: ");
setB = add(setB, in.nextInt () );
}
}
public static boolean setContainsValue (int set, int value)
{
boolean setContainsValue = (set & maskForValue) != 0;
return true;
}
public static int addValueToSet (int set, int newValue)
{
set = set | maskForValue;
return set;
}
public static void printSet (int set, int value)
{
int mask = 1;
System.out.print ("{");
for (int i = 0; i<= 9; i++)
{
if(( mask & set ) == 1)
System.out.print(i + " " );
int maskForValue = 1 << value;
set >>= 1; //set = (set >> 1);
}
System.out.println ("} ");
}
}
I am having trouble with an assignment for school. We are given the universal set U = {0-9}. I have to gather user input for both sets, and then use bit strings (we are not allowed to use the Set or HashSet classes in java) to store the sets and perform operations on them, such as complement, Set A union Set B and such. I know how to do those, but my code does not convert Sets A and B into the memory correctly and therefore, I cannot perform any operations on them. Help will be gladly appreciated! Thanks in advance. :)
Edit 1:
Alright, I read your ideas and tried to implement them as good as I could, and I have given the result above. This program really pushes me out of my comfort zone and I really appreciate all the help.

First of all, do yourself a favour and create helper methods. Then concentrate only on making them correct:
public static boolean contains(int set, int value) {
//return true if value bit is 1 in set
}
public static int add(int set, int newValue) {
//add newValue to set and return it
}
Afterwards you can express your logic more clearly:
if ( contains(set, 1) ) {
//print 1
}
Some general hints:
Don't use Math.pow() as that is made for floating-point numbers. To get a power of 2 as an integer, use bit shifting:
int maskForValue = 1 << value;
To check if a certain bit is set, find the mask for that bit and use &. This zeros out all bits except for the bit you're checking.
boolean setContainsValue = (set & maskForValue) != 0;
To set a bit in a bit field, find the mask for that bit and use |. This ensures that that bit becomes 1.
set = set | maskForValue;
Edit
As to your direct problem, take a look at this:
for (int i = 1; i <= elementsSetB; i++)
{
System.out.println ("Please enter integer number " + i + " in set B: ");
setB = in.nextInt ();
}
You're overwriting setA and setB every time. In the end, setA and setB will contain the last value the user specified. Then later, you do this:
for (int i = 0; i <=9; i++)
setB |= (int)pow(2.0, i-1);
Which just ignores the user's input and overwrites all bits 0-9 (though in an unsafe way!). So of course what the user inputs is irrelevant.
Get rid of the latter for loops and then store the input like this (using the helper methods I described above):
for (int i = 1; i <= elementsSetB; i++)
{
System.out.println ("Please enter integer number " + i + " in set B: ");
setB = add(setB, in.nextInt());
}
Edit 2
You seem to be having problems understanding where I'm coming from with my idea of these "helper" methods. If this is the first time you've worked with methods that have parameters, sorry for clouding up the issue. But they allow you to focus on getting one piece of functionality working at a time. I'll expand on what I mean more here:
public static boolean setContainsValue(int set, int value) {
//return true if the bit string (or bit set) represented by the "set" parameter
//contains the value stored in the "value" parameter
//see the FIRST and SECOND bullet points above for how to do this
}
public static int addValueToSet(int originalSet, int valueToAdd) {
//add the value stored in the "valueToAdd" parameter to the set represented by the
//"originalSet" parameter and return the result
//see the FIRST and THIRD bullet points above for how to do this.
}
I'll even write some tests for you too. The methods above haven't been implemented properly until at least all of the following print true:
int set = 0;
System.out.println( ! contains(set, 1) ); //make sure set doesn't contain 1
set = addValueToSet(set, 1);
System.out.println( contains(set, 1) ); //make sure set now contains 1
System.out.println( !contains(set, 2) ); //make sure set doesn't contain 2
set = addValueToSet(set, 2);
System.out.println( contains(set, 1) ); //make sure set still contains 1
System.out.println( contains(set, 2) ); //make sure set now contains 2

First, you need a class (this is object-oriented programming, right?) to contain the "DigitSet".
public DigitSet {
private BitSet digits;
public DigitSet() {
// digits contains one bit for each digit
digits = new BitSet(10);
}
... rest of DigitSet code goes here, like ...
/**
* Check if this set contains a particular digit.
*/
public boolean contains(int value) {
// check to see if value is a valid input (0-9)
// look in digits to see if the "right" bit is set.
}
public void set(int value) {
// check to see if value is a valid input (0-9)
// set the "right" bit in digits to 1.
}
public void clear(int value) {
// check to see if value is a valid input (0-9)
// set the "right" bit in digits to 0.
}
public DigitSet union(DigitSet other) {
// construct a "new" output DigitSet.
// Walk through all of the digits in "this" set
// if a digit is set in this set, set it in the output set.
// Walk through all of the digits in the "other" set
// if a digit is set in the other set, set it in the output set.
}
public String toString() {
// return a display string based on the set "digit" bits
}
}
Then the rest is just input handling and "perform the operation"
public static void main(String[] args) {
DigitSet first = new DigitSet();
// read in the values for the first digit set, for each value
// set the digit in first like so
first.set(value);
DigitSet second = new DigitSet();
// read in the values for the second digit set, for each value
second.set(value);
DigitSet result = first.union(second);
System.out.println("Result: " + result.toString());
}

Related

Return more than one variable from a Java method

Your program must read the id number and gpa and transfer the data into two separate arrays. You can assume there will never be more than 1000 students in the file. Do you know why you must use two separate arrays? You may find it useful in this program to create additional arrays to complete the requirements of the program as described next.
Your program must do two distinctly different things correctly for full credit:
You must create a simple diagram to show how many students fall into each of 8 different categories. This type of diagram is known as a histogram and it is generally useful to show how data is distributed across a range.
For each student in the input file, you must display their S-number, gpa, and class rank. The S-number and gpa will already be in your arrays; however, you must calculate their class rank.
Here is the code I have so far:
public static void main(String[] args) throws Exception
{
Scanner gpadata;
String snum;
double gpa;
int groupNumber;
gpadata = new Scanner(new File("studentdata.txt"));
while (gpadata.hasNext())
{
snum = gpadata.next();
gpa = gpadata.nextDouble();
groupNumber = gpaGroup(gpa);
System.out.println("Student number, GPA, and group number"
+ " is: " + snum +
" " + gpa + " " + groupNumber);
}
}
//Method to categorize students GPA into 1 of 8 groups
public static int gpaGroup(double gpa)
{
//Declare all variables
int gpaGroup;
//Assign GPA a group number
if (gpa >= 0.0 && gpa < 0.5)
gpaGroup = 1;
else if (gpa >= 0.5 && gpa < 1.0)
gpaGroup = 2;
else if (gpa >= 1.0 && gpa < 1.5)
gpaGroup = 3;
else if (gpa >= 1.5 && gpa < 2.0)
gpaGroup = 3;
else if (gpa >= 2.0 && gpa < 2.5)
gpaGroup = 4;
else if (gpa >= 2.5 && gpa < 3.0)
gpaGroup = 5;
else if (gpa >= 3.0 && gpa < 3.5)
gpaGroup = 6;
else
gpaGroup = 7;
//Return int value of group number
return gpaGroup;
}
//Method to find number of students in each group
public static void studentsInGroup(int gpaGroup)
{
//Declare all variables
int gpaGroup1 = 0;
int gpaGroup2 = 0;
int gpaGroup3 = 0;
int gpaGroup4 = 0;
int gpaGroup5 = 0;
int gpaGroup6 = 0;
int gpaGroup7 = 0;
int gpaGroup8 = 0;
//Total students in each GPA group
if (gpaGroup == 1)
gpaGroup1++;
else if (gpaGroup == 2)
gpaGroup2++;
else if (gpaGroup == 3)
gpaGroup3++;
else if (gpaGroup == 4)
gpaGroup4++;
else if (gpaGroup == 5)
gpaGroup5++;
else if (gpaGroup == 6)
gpaGroup6++;
else if (gpaGroup == 7)
gpaGroup7++;
else
gpaGroup8++;
}
Can I modify my method to return more than one variable from a method (in public static void studentsInGroup(int gpaGroup) return values of number of students in each group)? Is this where arrays start to come in? From here I would write another method to round number of students in each category to the nearest ten, then use this to write a method for creating a histogram etc etc.
I have been trying my hardest to understand the concepts, but I have been struggling lately. This is one of my last assignments for the semester and I'd like to keep my A, and also understand what I'm doing.
Can I modify my method to return more than one variable from a method (in public static void studentsInGroup(int gpaGroup) return values of number of students in each group)?
Yes, you can. You can create an object that contains two variables. However, the instructions suggest a different solution.
Inside your loop, read the id and gpa, and immediately stick them in two separate arrays.
Here is a fragment:
snums = [];
gpas = [];
while (gpadata.hasNext())
{
snum = gpadata.next();
gpa = gpadata.nextDouble();
snums.append(snum);
gpas.append(gpa);
}
ensure you are doing the following. I'm not giving away any code here. Also not sure why they want you to use array only!?!
Breakdown your requirement and see what you need to achieve.
Start with reading each line from file
each line is separated by " " and has id_number and gpa
from the requirement, the file will not contain more than 1000 students(1000 lines). You may declare this as a static class level variable static String[] idnum_array = new String[1000]; and another array for gpa which is Double[]
read each line and then separate by using String.split(" ") method. The first variable is your id number and 2nd will be your gpa. you follow ?
maintain a separate counter to increment the array position each time you set these values in the two arrays you created in step 3.
Integer i = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] splitString = line.split(" ");
idnum_array[i] = String.valueOf(splitString[0]);
gpa_array[i] = Double.valueOf(splitString[1]);
i++;
}
Do you agree that if we do idnum_array[7] to return it's corresponding gpa result from gpa_array[7] for that student ?
How you choose to count the number of people in a certain group is upto you.
I would do the following
create a static class level variable static Integer[] group_array = new Integer[]{0,0,0,0,0,0,0,0}; // there are only 8 groups!
loop my gpa_array
have an if/else inside the loop to check which group it falls in
increment the value at that index by 1. group_array[index]++;
In the end I will have an array of 8 elements which will correspond to the 8 groups. [0,200,300,200,0,300,0,0,0]
You should end up with nearly 4 methods similar to this.
1. readDataFromFile(String fileName)
2. groupGPAIntoCategory()
3. drawHistogram()
4. calculateRank()
I would personally create a Student object from the very beginning.
It's just cleaner and readable. Make sure you have your try catch block to print your exceptions and always comment!

Variable value not correctly increasing

In my code I have a variable, points, that increments based on the consanants and vowels in strings inputted. The method parseSentence is supposed to increase points per word but also ignore spaces.
I've tried running a debugger to see where the problem is but the debugger dies when it reaches the for loop in parseSentence. The method makes the point variable's value the word's point value instead of adding it to the variable. What could be causing this?
import java.util.*;
public class WordGolf1 {
public static int points = 1;
public static void main(String[] args) {
String Input;
System.out.println("Enter word: ");
Scanner sc = new Scanner(System.in);
Input = sc.nextLine();
System.out.println("Not enough points. " + (100 - points) + " needed.");
while (points < 100) {
System.out.println("Enter word: ");
Input = sc.nextLine();
parseSentence(Input);
System.out.println(points + ": points");
System.out.println("Not enough points. " + (100 - points) + " needed.");
}
boolean overshot = true;
Loop:
while (overshot = true) {
if (points == 100) {
overshot = false;
break Loop;
}
points = 100 - (points - 100);
System.out.println("Overshot by " + (points - 100) + " points.");
Input = sc.nextLine();
parseSentence(Input);
}
System.out.println("Congratulations you win!");
sc.close();
}
public static int parseSentence(String input) {
String[] pieces = input.split("\\s+");
for (int y = 0; y < pieces.length; y++) {
if (pieces.length > 1) {
if (y == 0) {
parseWord(input);
} else {
parseWord(input, y);
}
} else {
parseWord(input);
}
}
return points;
}
public static int parseWord(String input) {
String[] pieces = input.split("\\s+");
String charList = "aeiouyAEIOUY";
String consanantList
= "bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ";
int pointsTemp = 1;
for (int x = 0; x < pieces[0].length(); x++) {
if (charList.indexOf(pieces[0].charAt(x)) != -1) {
pointsTemp *= 2;
} else if (consanantList.indexOf(pieces[0].charAt(x))
!= -1) {
pointsTemp++;
}
}
points = pointsTemp;
return points;
}
public static int parseWord(String input, int number) {
String[] pieces = input.split("\\s+");
String charList = "aeiouyAEIOUY";
String consanantList
= "bcdfghjklmnpqrstvwxzBCDFGHJKLMNPQRSTVWXZ";
int pointsTemp = 1;
for (int x = 0; x < pieces[number].length(); x++) {
if (charList.indexOf(pieces[number].charAt(x)) != -1) {
pointsTemp *= 2;
} else if (consanantList.indexOf(pieces[number].charAt(x)) != -1) {
pointsTemp++;
}
}
points += pointsTemp;
return points;
}
}
You are not using the value returned by the parseSentence method.
Edit: I tried to rewrite this to be as close your original code with making the changes I feel where necessary.
Now Obviously your teacher has requirements and we can't go against that, but some points of interest you should keep in mind.
Multi Splitting
In your example you split the text to get the amount of words. Then instead of looping the already split text. You are sending the original input and then splitting it again. The "Double" splitting is why you needed "three" methods. If you don't double split you can simply loop the length from the single split and just use a single ParseWord method.
Deducting Values
In your example you take away 100 if the player overshot. The problem with this is let's say the person received a score like 200. Then it would loop twice to lower the value submitting the "You overshot message" twice. However let's say by some magical way a score of 100,000,000 was received. Then as you can see we would loop 1 million times to deduct this value essentially creating an not infinite but might as well be infinite loop.
To resolve this problem we simply do the below.
Value = Value % 100.
This will give us the remainder of our Value between 0 and 99. I.e. 167 will equal 67 and 12384 will be equal 84.
Using String (IndexOf)
What this does is takes the Character you provided and loop iterates over the String you provided. The worst case is 12 loops. There's also a lot of other stuff String and IndexOf do that is extra work and I recommend staying away from it if you can.
The alternative solution which I did is take the character and use " | 32" on it. I'm not going to go deep into how bits work, but basically these characters are 8 bit values but we only use 7 of it's bits ranging from 32 to 127. The amount of bits is like the power of 2. so 2^7 = 128 and 2^8 = 256. When we perform the "|" we are turning a bit on so if it's already on it won't change the value.
So in our example let's say we have the value 64.
This is bit 6 turned on. Now we want to turn on bit 5 "32" so the value becomes 96, but if we already had the value 96 and we turn bit 32 on it will still be 32.
Full List of ASCII Characters..
https://www.ascii-code.com/
The Game Loop
In your example you created "TWO" game loops the first one is when you start off, but once you overshot your score you enter the second loop and forget the first one. The problem is now your "Enter Words" and "You Undershot" code are never used anymore. So all someone will see is the line to enter text with no information on what to do or what occurred unless they overshot then they get the overshot message.
To fix this I made a single Game Loop which processes until the code ends via the SCORE == 100. You can see in the code that we begin every game loop with "Enter Words: " and parse the sentence. Then we add up our score and compare. If we undershot we simply restart the loop and try again. If we overshot we reduce the score and try again. If we succeeded we prompt the user if they would like to play again or end the game. Playing again will set the SCORE to 0 and start over the loop. Ending the game will "BREAK" the loop and cause it to end.
The Full Working Code With Recommended Changes
Feel free to comment if you need additional assistance.
import java.util.*;
public class WordGolf1
{
private static int SCORE = 0;
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
while (true)
{
System.out.print("\n\nEnter word: ");
ParseSentence(sc.nextLine());
if (SCORE == 100)
{
System.out.print("\nYou Won! Would you like to play again: Y/N?");
if ((sc.nextLine().charAt(0) | 32) == 'y')
{
SCORE = 0;
System.out.print("\nResetting Game...");
} else {
break;
}
}
else
{
if (SCORE > 100)
{
int overshot = SCORE - 100;
SCORE = SCORE % 100;
System.out.print("\nYou Overshot By " + overshot + " Points. You now have " + SCORE + " points.");
} else {
System.out.print("\nYou currently have " + SCORE + " points you need " + (100 - SCORE) + " more.");
}
}
}
}
private static int ParseSentence(String input)
{
String[] split = input.split(" ");
for (Strng s : input)
SCORE += ParseWord(s);
}
private static int ParseWord(String word)
{
int value = 1;
for (int i = 0; i < word.length(); ++i)
{
int c = (int)word.charAt(i) | 32;
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
{
value *= 2;
} else {
value += 1;
}
}
return value;
}
}

Number guessing game keeps repeating same questions and guesses incorrectly

If you run the the game you can see that certain numbers the game cannot guess correctly. For example if your number is 13 the game will loop two times too many and will also guess your number as 12 instead of 13. I think this is an issue with the counting but I've tried tracing the loops repeatedly but cannot find the error. I think the issue mainly lies within my while loop.
//import statements
import java.util.Scanner;
public class Numbers
{
public static void binarySearch()
{
int position=0;
String answer;
int upper_BOUND=100;
int lower_BOUND=0;
Scanner input=new Scanner(System.in);
while( (lower_BOUND <= upper_BOUND))
{
position = (lower_BOUND + upper_BOUND) / 2;
System.out.println("Is your value greater than " + position + "?");
answer=input.next();
if((upper_BOUND-lower_BOUND<=1))
{
break;
}
if (answer.equals("no")) // If the number is > key, ..
{ // decrease position by one.
upper_BOUND = position --;
}
if(answer.equals("yes"))
{
lower_BOUND = position ++; // Else, increase position by one.
}
}
System.out.println("Is your number " + position + "?");
String answer2=input.next();
System.out.println(position+" is the answer.\n Thank you for playing the guessing game.");
//else
// System.out.println("Bruh pick a number from 1 to 100 ");
}
}
......
tester class
public class NumberGuesser
{
public static void main(String[] args)
{
int[ ] num = new int [100];
// Fill array
for (int i = 0; i <= 99; i++)
num[i]=i;
//The search method
Numbers.binarySearch();
}
}
Your issue should be with the increment that you do in "lower_BOUND = position ++; " here what happens is when you increment the position value, the "++" first increments and then assigns the value to position variable. The lowerbound is not actually assigned the incremented value of position but old value of positon. So please make a change to "lower_BOUND = ++ position ; "
Like below
if(answer.equals("yes"))
{
lower_BOUND = ++ position ; // Else, increase position by one.
}
And also my suggestion is to check your " if((upper_BOUND-lower_BOUND <= 1))" condition. I guess the condition should be like this " if((upper_BOUND-lower_BOUND == 0)) "
And please remove unused code in your "NumberGuesser" class, this will confuse people who are trying to answer your question.

ArrayIndexOutOfBounds Exception on employee database program

I am very new to java and have been trying to get my bearings with it. I've been trying to write an proof of concept employee database. It all works fine until I enter the last employee condition, then I get an ArrayIndexOutOfBoundsException. Here is the code for both of my files. Any help would be appreciated.
import java.util.Scanner;
public class EmployeeInterface
{
public static void main(String[] args)
{
Scanner Input = new Scanner(System.in);
System.out.println("Please enter the number of employees to register.");
int employeeCount = Input.nextInt();
Employee.setEmployeeNumber(employeeCount);
String employeeFullName;
String employeeAddress;
String employeeDateOfHire;
for(int x = 0; x <= employeeCount; x++)
{
System.out.println("Please enter the full name of employee number " + (x + 1));
Input.nextLine();
employeeFullName = Input.nextLine();
System.out.println("Please enter the address of employee number " + (x + 1));
employeeAddress = Input.nextLine();
System.out.println("Please enter the date of hire for employee " + (x + 1));
employeeDateOfHire = Input.nextLine();
Employee.employeeRegister(x, employeeFullName, employeeAddress, employeeDateOfHire);
}
}
}
Here is the second file:
public class Employee
{
private static int employeeCount;
private static String employees[][] = new String[employeeCount][4];
public static void setEmployeeNumber(int x)
{
employeeCount = x;
}
public static void employeeRegister(int employeeNumber, String employeeFullName, String address, String employeeHireDate)
{
employees[employeeNumber][0] = employeeFullName;
employees[employeeNumber][1] = employeeFullName;
employees[employeeNumber][2] = employeeFullName;
employees[employeeNumber][3] = employeeFullName;
}
}
This is the problem:
for(int x = 0; x <= employeeCount; x++)
You're using <= rather than <. So if employeeCount is 3, you'll actually ask for the details of 4 employees, and use indexes 0, 1, 2 and 3 - but 3 is an invalid index for an array of size 3.
Your setEmployeeCount method is also broken - it changes the value of employeeCount, but doesn't reinitialize the array, so you'll always end up with an array of size 0. Given that you've said the code works until the final entry, I suspect this isn't a problem in your real code, as otherwise you'd get an exception on the very first entry.
That said, I would strongly recommend that you create a rather more useful Employee type, with private instance fields for number, name etc... then create a List<Employee>. (There's probably no point in it being stored via a static field in Employee either - what if you want two employee lists?)
Additionally, an employeeHireDate should be in some appropriately chronological type - not a string. (I'd suggest using LocalDate from Joda Time as the built-in Java types for date/time types are awful.)
In addition to other answers:
private static String employees[][] = new String[employeeCount][4];
employeeCount is immediately intialized as 0 and so is the array afterwards.
You need to reintialize your array after setting employeeCount.
your loop is iterating 1 extra time. if employeeCount is 5 then loop iterates 6 times.
Try this instead
for(int x = 0; x < employeeCount; x++)
ArrayIndexOutOfBounds Exception
because you are trying to access the 1 index more which doesn't exist by using <= instead of < only
use for(int x = 0; x < employeeCount; x++)
instead of
for(int x = 0; x <= employeeCount; x++)`
Additionally to other answers:
In the method setEmployeeNumber(int x), you only change the variable employeeCount. What's missing here is to resize the array wherein you store the employees:
employees[][] = new String[employeeCount][4];

Utilizing recursion to compute a series

I must be failing to wrap my head around the concept of trying to store a value in a recursive method. Solving this using iteration would take seconds, but I am struggling with the recursive call. Basically I am trying to solve: 1/1 + 1/2 + 1/3 ...
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter in the end number for the sequence: ");
int endpoint = input.nextInt();
System.out.println("The value of the sequence is : " + calcSequence(endpoint));
}
public static double calcSequence (int index){
if (index == 0)
return 0;
else
return (1/index) + calcSequence(index - 1);
}
You need to add some explicit type conversions. Your 1/index is being performed as integer division, and your call is losing all its precision. Simply changing this to 1.0/index (or 1d/index to indicate that the 1 should be used as a double) should get you what you're looking for.

Categories

Resources