Java: How to compare every two elements in an array once? - java

This is an assignment we have and I'm a little bit lost with his directions. He tells us to write a program with a method called equals to compare the salary of EVERY TWO EMPLOYEES in the array (I've already created this) and prints the SSN of every two employees that have the same salary in pairs. He made a disclaimer that
the code should only compare two different employees and only once. Every two different employees are compared only once. The array is size 10.
I've already asked multiple peers on what he meant but they are also confused. This is what I have:
For the Class:
public boolean equals(Employee e)
{
boolean status;
if(salary == e.getSalary())
{
status = true;
}
else
status = false;
return status;
}
For the Demo:
for(int i = 0; i < employees.length; i++)
{
for(int j = i+1; j < employees.length; j++)
{
if(employees[i].equals(employees[j]))
System.out.println(employees[i].getSsn() + "\t" +
employees[j].getSsn());
}
}
It compiles, however it skips comparing index 0 and index 1. Any help is appreciated.

Initialize j with int j = i+1 instead of int j = i+2

Related

Finding index of an item within a 2D Array

After some research, I found out how to find the index of an item within a 2D Array. However, I'm after just one value, the row number and also what if the item you are looking for appeared more than once?
How would you store the row number of all those times?
for(int j = 0; j < size; j++)
{
if (arr[i][j] == 88)
{
return i; // The value i wanna store
break;
}
}
If the number 88 appears more than once, how can I store all the different locations and later retrieve it?
You could store the values you want in a List.
List<Integer> rows = new ArrayList<>();
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (arr[i][j] == 88) {
rows.Add(i); // The value i wanna store
break; // exit inner loop and continue with next row
}
}
}
i'm after just one value, the row number
But if 88 appears more than once, how can I store all the different
locations and later retrieve it?
Considering you don't know how many duplicated copies of the value you're looking for there could be, I'd suggest using an ArrayList to store the indexes.
create this before the loops:
List<Integer> indexList = new ArrayList<>();
then within the if block simply add the index value for the value you've found to the ArrayList:
if (arr[i][j] == 88){
indexList.add(i);
break;
}
you can then return the ArrayList if your method requires returning the data:
return indexList; // after the loops have finished processing
However, if the method return type is void then you can simply ignore the return indexList;

Java - Multidimensional Arrays How to test an array for all unique values

I'm trying to test a multidimensional array to see if contains any duplicate values. If it does I would like the method to return false. Otherwise I would like it to return true.
Here is my current code. Where is my logic wrong?
public static boolean isUnique(int[][] array2, int num) {
for (int i = 0; i < array2.length - 1; i++) {
for (int j = i + 1; j < array2.length; j++) {
if (array2[i] == array2[j]) {
return false;
}
}
}
return true;
}
Your current implementation is checking whether two rows are the same (this is a reference based check, rather than a value.) This means that it asks 'Are array2[i] and array2[j] the same address in memory, rather than do they contain the same things.
If you want to see whether the rows are unique you'd use array2[i].equals(array2[j]) instead of array2[i] == array2[j].
If you wanted to check for unique elements (array[i][j] != array2[i+m][j+n] where !(m == n == 0)) you'd need to iterate through both levels in a
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
// compare array2[i][j] to all other array2[m][n] here.
}
}
Right now your code is checking whether any of the arrays inside array2 are the same. array2[i] and array2[j] are both referring to arrays, because array2 is an array of arrays.
Instead, you want to look at the values inside of each of those arrays. Since you want to fail on any repeated value anywhere in the grid, you're effectively trying to flatten the structure into one collection, and check for duplicates in that.
A HashSet is the best data structure to use in this case. Traverse the entire grid, row-by-row, adding values into your new struture. If you encounter a duplicate, return false:
public static boolean isUnique(int[][] array2) {
Set<Integer> values = new HashSet<>();
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
if (!values.add(array2[i][j])) {
return false;
}
}
}
return true;
}
Some things to note here:
The set's add method will return false if you attempt to add a duplicate to the collection, so that's wrapped in an if statement for a simple, fail-fast stopping condition.
The sizes of each of the inner arrays are completely independent from the size of the outer array, so you still want to loop from 0 to the length of the array (when you're using <, you don't need the length - 1).

finding the number of pairs of numbers in an array that add up to a number

I am trying to come up with a program that will search inside of an array that is given a length by the user that picks out whether there is a pair of numbers that sum to 7. The idea is that if there is k amount of dice being thrown, how many pairs of numbers out of those dice thrown add up to 7. So far this is all that I could come up with but I am very stuck.
This is the driver class for the program. I have to write a class that will make this driver function properly.
import java.util.Scanner;
public class SevenDriver{
public static void main(String[] args){
System.out.println("Enter number of dice to toss");
Scanner s = new Scanner(System.in);
int diceCount = s.nextInt();
SevenTally t = new SevenTally(diceCount);
int experiments = 1000000;
int wins = 0;
for(int j = 0; j < experiments; j++)
if(t.experiment()) wins++;
System.out.println((double)wins/experiments);
}
}
This is what I have so far. It does not currently work or compile. I am just looking for some ideas to get me going. Thanks!
public class SevenTally{
private int diceCount;
public SevenTally(int die){
diceCount = die;
}
public int genDice(){
return 1 + (int)(Math.random()*6);
}
public boolean experiment(){
boolean[] nums = new boolean[diceCount];
int ranNum;
int sum = 7;
for(int i = 0; i < nums.length; i++){
ranNum = genDice();
if (nums[ranNum] == sum){
return true;
}
}
int left = 0;
int right = nums.length - 1;
while(left<right){
int tempSum = nums[left] + nums[right];
if(tempSum == 7){
return true;
}
else if(tempSum>7){
right--;
}
return false;
}
}
First populate your array of length k with random int in [1;6]
The number of possible pairs in an array of length k is the number of 2-combinations in the array, which is (k-1)*k/2 (http://en.wikipedia.org/wiki/Combination)
You can test all the possible pairs (i,j) in your array like so:
int win = 0;
int tally = 7;
for(int i=0; i<k-1; i++){
for(int j=i+1; j<k; j++){
if(array[i]+array[j] == tally){
win++;
}
}
}
What this does is that it sets the first element of the pair to be the first element of the array, and sums it with the other elements one after the other.
It pairs array[0] with array[1] to array[k-1] at the first pass of the i for loop, that's k pairs.
Then k-1 pairs at second pass, and so on.
You end up with (k)+(k-1)+(k-2)+...+1 pairs, and that's exactly (k-1)*k/2 pairs.
done =]
edit: sorry, haven't read the whole thing. the method experiment() is supposed to return a boolean. you can return win>0?true:false; for example...
This Wiki page has some algorithms to do that. Its not a trivial problem...
You're generating a random number in ranNum, and then using it as an index into the array nums. Meanwhile, nums never gets filled, so no matter which box you index into, it never contains a 7.
What you want to do, if I understand your problem correctly, is fill each space in the array with the result of a die roll, then compare every two positions (rolls) to see if they sum to seven. You can do that using a nested for loop.
Essentially, you want to do this: (written in pseudocode as I'm not a java programmer)
int[] results[numrolls]
for (count = 0 to numrolls-1) { results[numrolls]=dieRoller() }
for (outer = 0 to numrolls-2)
for (inner = outer+1 to numrolls-1)
if (results[outer] + results[inner] == 7) return true
return false;
However, in this case there's an even easier way. You know that the only ways to get a sum of 7 on 2d6 are (1,6),(2,5),(3,4),(4,3),(5,2),(6,1). Set up a 6-length boolean array, roll your dice, and after each roll set res[result] to true. Then return (1-based array used for simplicity) ( (res[1] && res[6]) || (res[2] && res[5]) || (res[3] && res[4]) ).
ArrayIndexOutOfBoundsException means you are trying to access an element of the array that hasn't been allocated.
In your code, you create a new array d of length diceCount, but then you genDice() on always 6 elements.

Gets the number of duplicates in the list - wrong output

How to count duplicates in ArrayList and count only once.
Here is what I have so far:
/**
* Gets the number of duplicates in the list.
* Get the next word. It is at index i. Does it match any of the words with index > i?)
* #return the number of duplicate words in the list
*/
public int countDuplicates() {
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i; j < list.size(); j++) {
if (list.get(i).equals(j)) duplicates++;
}
}
return duplicates;
}
Here is check output:
Actual: 0
Expected: 3
I am missing something very easy. However, couldn't find what exactly it is.
How to solve this trouble?
You don't get the jth element you just compare to j directly. And as a commenter points out, j should start at i+1 to avoid comparing an element to itself. Therefore, you need to write
public int countDuplicates()
{
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i+1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Should be:
public int countDuplicates()
{
int duplicates = 0;
// TODO: Write the code to get the number of duplicates in the list
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Use two sets for this:
final Set<X> set = new HashSet<>();
final Set<X> dups = new HashSet<>();
int dupCount = 0;
for (final X x: list) {
if (set.add(x)) // first time the element is seen
continue;
// Dup; see whether it is the first time we see it
if (dups.add(x))
dupCount++;
}
return dupCount;
This relies on the fact that Set's .add() returns true if and only if the set has been modified as the result of the operation. And note that it traverses the list only once.
I can see three problems with your current code:
You are not comparing pairs of elements. You are actually comparing an element with an index.
Your inner loop is comparing element i and element i ... and that would result in a false "duplicate" count.
If you have more than 2 copies of any given element, then you will get too many duplicate counts. (To see why, try to "hand execute" with a list of (say) three identical elements.
In fact, you have to EITHER use an auxiliary data structure (e.g. 2 Sets or a Map) OR modify the input list to avoid counting duplicates more than once.
I would note that your statement of the problem is ambiguous. "... only count each duplicate once" could mean that '[1, 1, 1]' gives either 1 or 2. It depends whether you consider each individual 1 to be a duplicate to be counted once or that we have 1 as one of a set of duplicates ... that must only be counted once.
You are comparing index j value instead of value of list list.get(j).
Do
if (list.get(i).equals(list.get(j)))
instead of
if (list.get(i).equals(j))

Comparing poker hand in java

I am working on a poker game. So far I am stuck on comparing poker hands. I sort of have an idea on how to do it but I am not sure what is wrong with my code. Can somebody please point out what's wrong?
So let me give a brief description of what my code is doing.
My other part of the program will go through the cards in my hand and list the frequency of a card value in an array.
h = Hearts
c = Clubs
d = Diamonds
s = Spades
d4 = 4 of Diamond
So let's say in my hand I have
c3, h4, d4, s4, 2d
I will call the other part of my program to read the cards in my hand and return a tally array. The tally array for my hand above will be [0,0,1,1,3,0,0,0,0,0,0,0,0,0] So pretty much what this array is saying is that my hand has one 2, one 3 and three 4.
Now here is my method on trying to find Three of a Kind, it should return false for full house (which is three of a kind plus a pair)
public boolean hasThreeOfAKind() {
int [] temp;
temp = this.getCounts();
for (int i = 0; i< temp.length; i++){
if (temp [i] == 3 ){
for (int j = 0; j < temp.length ; j++)
if ( temp [j] != 2){
return true;
}
}
}return false;
So what I am trying to do above is first, I run through the array, and if if there is any 3. If there is a 3, I run through the array again and see if there is a 2. and if there is not a 2, then I know it is three of a kind. If there is a 2, then it is full house and I should return false. I think my logic is correct, but there is something wrong with my code.
And the second hand that I am having trouble is how to determine if my hand has EXACTLY one pair. It only return true if there is only one pair. Return false if there are two pairs etc.
public boolean hasOnePair() {
int [] temp;
temp = this.getCounts();
for (int i = 0; i< temp.length; i++){
if (temp [i] == 2 ){
return true;
}
}return false;
For this one, I am thinking of sort the value in the array either in descending or ascending order. If I chose the descending order, I first read the array and see if there is a 2, then I could scan the next one and see if the next value after the first 2 is also a 2. If there is another 2, then it would return false.
Can somebody please take a look at my code and point out what's wrong? Thank you very much.
Why are you working with such low level primitives? Is there a reason you're not using a full fledged Card class? Your code would be much simpler.
class Card
enum Value {
TWO,
...
ACE
};
enum Suit {
SPADES,
...
CLUBS
};
private Suit suit;
private Value value;
public Card(Suit suit, Value value) {
this.suit = suit;
this.value = value;
}
}
public class Hand {
private final List<Card> cards;
public Hand(Card first, Card second, Card third, Card fourth, Card fifth) {
// add to cards list.
// sort ascending by value
}
public boolean hasThreeOfAKind() {
for (int i = 0; i < 3; i++) {
Value firstValue = cards.get(i).getValue();
Value secondValue = cards.get(i+1).getValue();
Value thirdValue = cards.get(i+2).getValue();
if (firstValue == secondValue && secondValue == thirdValue) {
return true;
}
}
return false;
}
}
This doesn't directly answer your question, but in my opinion this sort of code is much more readable and maintainable and will be easier to debug than one involving only integers. Java isn't C and you don't really gain much by treating it like C.
In your hasThreeOfAKind() you have the following error:
for (int j = 0; j < temp.length ; j++)
if ( temp [j] != 2){
return true;
}
}
This will return true the first time it finds a non-2 j (which will be statisfied with the 3 you just checked above it -- thus returns true for a full house. You need instead:
boolean foundTwo = false;
for (int j = 0; j < temp.length ; j++)
if ( temp [j] == 2){
foundTwo = true;
}
}
if (!foundTwo) {
return false;
}
Similarly for the other: you need to check if you find another 2 that is different from the one you already found:
for (int i = 0; i< temp.length; i++) {
if (temp [i] == 2 ){
boolean foundAnother = false;
for (int j = 0; j< temp.length; j++) {
if (i != j && temp [j] == 2 ){
foundAnother = true;
}
}
if (!foundAnother) {
return true;
}
}
}
return false;
Another thing you could do is have filters for each recognized hand: a pair-filter, a three-filter, a full-house-filter, etc. and run all those filters through the hand. Don't worry if there is a better (higher value) match, just see which filters return true (found the pattern they were looking for) and select the highest point value among the ones that passed
In your threeOfAKind method, the second for loop will only get executed once unless the first number stored in your array is a 2, it should look more like this:
public boolean hasThreeOfAKind() {
int [] temp;
temp = this.getCounts();
for (int i = 0; i< temp.length; i++){
if (temp [i] == 3 ){
for (int j = 0; j < temp.length ; j++)
if ( temp [j] == 2){
return false;
}
}
}
return true;
}
in the above code, the first time it hits a pair it realizes that the hand is a full house instead of a three of a kind, and returns false.
and as for your other method hasOnePair() it should look more like:
public boolean hasOnePair() {
int [] temp;
temp = this.getCounts();
int count = 0;
for (int i = 0; i< temp.length; i++){
if (temp [i] == 2 ){
count++;
}
}
return count == 1;
}
Look for the number of each similar card and make arrays. SO cards{1,1,2,2,2,5,7} (lets ignore the suits for now) will map to (3,2,1,1) i.e a full house you can check the second array easily
I'm helping my son with a similar problem for his Java Course at college (the course I used to teach) and this is what I would suggest.
First sort your cards from lowest to highest 2 to Ace regardless of suit.
Then do comparing.
If card[0]==card[3] or card[1]==card[4], you have 4 of a kind, ignore next 2 lines.
If card[0]==card[2] or card[1]==card[3] or card[2]==card[4], you have 3 of a kind, ignore the next line.
If card[0]==card[1] or card[1]==card[2] or card[2]==card[3] or card[3]==card[4], you have a pair.

Categories