Element of a Set randomly changing - java

For some reason one of the elements of Set s are changing randomly without my code altering it at any point. Not sure why the Set changes from:
[[red, green], [green, red], [red, red], [green, green]]
to
[[green, red], [green, red], [red, red], [green, green]]
for no reason.
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class Fermat {
public static void main(String[] args) {
Set<String> colours = new HashSet<String>();
colours.add("red");
colours.add("green");
analyse(threadings(2, colours));
}
public static Set<ArrayList<String>> threadings(int n, Set<String> s) {
Set<ArrayList<String>> combos = new HashSet<ArrayList<String>>();
if (n < 0) {
combos.add(new ArrayList<String>());
return combos;
} else {
int[] index = new int[s.size()];
do {
ArrayList<String> newCombo = new ArrayList<String>();
for (int i = 0; i < n; i++) {
newCombo.add(s.toArray(new String[s.size()])[index[i]]);
}
combos.add(newCombo);
index[index.length - 1]++;
for (int i = (index.length - 1); i > 0; i--) {
if (index[i] >= s.size()) {
index[i] = 0;
index[i - 1]++;
}
}
} while (index[0] < s.size());
return combos;
}
}
public static boolean isEquiv(ArrayList<String> a, ArrayList<String> b) {
if (a.size() != b.size()) {
return false;
} else {
for (int i = 0; i < a.size(); i++) {
if (a.equals(b)) {
return true;
}
Collections.rotate(a, 1);
}
return false;
}
}
public static void analyse(Set<ArrayList<String>> s) {
Set<ArrayList<String>> singletons = new HashSet<ArrayList<String>>();
ArrayList<ArrayList<String>> combos = new ArrayList<ArrayList<String>>();
for (ArrayList<String> combo : s) {
System.out.println(s);
if (singleton(combo, s)) {
singletons.add(combo);
}
}
System.out.println(singletons);
}
public static boolean singleton(ArrayList<String> c, ArrayList<ArrayList<String>> cs) {
for (int i = 0; i < cs.size(); i++) {
{
if (isEquiv(c, cs.get(i)) && !c.equals(cs.get(i))) {
return false;
}
}
}
return true;
}
}

You're mutating the lists with Collections.rotate(a, 1). In this case it ends up rotating that [red, green] to [green, red] at some point, and that affects every reference to that list object.
You need to create a new list and rotate that, so the original list object isn't changed. Something like this:
ArrayList<String> a2 = new ArrayList<>(a);
for (int i = 0; i < a2.size(); i++) {
if (a2.equals(b)) {
return true;
}
Collections.rotate(a2, 1);
}

Related

Java - create 2 different matrices with same variables

I'm currently working on a version of Conway's Game of Life with Netbeans IDE and I wanted to store cells in a matrix. For the operation of going to the Next generation of cells, I would return a new matrix of cells which is calculated from the inputting matrix.
The Code is the following:
public static Cell[][] nextGen(Cell[][] CellList)
{
Cell[][] Copy = CellList.clone();
for (int i = 0; i<Copy.length; i++)
{
for(int n = 0; n<Copy[i].length; n++)
{
if (Copy[i][n].isAlive())
{
if (Cell.count(Copy, i, n) <= 1 || Cell.count(Copy, i, n) >= 4 )
{
CellList[i][n].kill();
}
}else
{
if (Cell.count(Copy, i, n) == 3)
{
CellList[i][n].born();
}
}
}
}
return CellList;
}
The Class is called "Cell"
it has a private boolean property "alive" which can be set to false with the public method kill() or true with the public method born(). Everything except the method for counting alive cells surrounding a specific cell and the method for calculating the new generation is nonstatic.
The Problem why it isn't working is that if I make any changes to the input matrix "CellList", the same thing happens in the copy of this matrix.
How can I let the copy have the same Values but only make changes in the input matrix?
Thanks for the helping!
What you are doing is shallow copy, what you need is deep copy. Try this
public class Cell {
boolean alive = false;
protected Cell clone() {
return new Cell(this);
}
public Cell() {
}
public Cell(Cell cell) {
this.alive = cell.alive;
}
boolean isAlive() {
return alive;
}
void kill() {
alive = false;
}
void born() {
alive = true;
}
static int count(Cell[][] cell, int j, int k) {
return 1;
}
public static void main(String[] args) {
Cell[][] CellList = new Cell[2][3];
CellList[0][1] = new Cell();
nextGen(CellList);
}
public static Cell[][] nextGen(Cell[][] CellList) {
Cell[][] Copy = deepArrayCopy(CellList);
for (int i = 0; i < Copy.length; i++) {
for (int n = 0; n < Copy[i].length; n++) {
if (Copy[i][n].isAlive()) {
if (Cell.count(Copy, i, n) <= 1 || Cell.count(Copy, i, n) >= 4) {
CellList[i][n].kill();
}
} else {
if (Cell.count(Copy, i, n) == 3) {
CellList[i][n].born();
}
}
}
}
return CellList;
}
public static Cell[][] deepArrayCopy(Cell[][] celllist) {
Cell[][] copy = new Cell[celllist.length][celllist[0].length];
for (int i = 0; i < celllist.length; i++) {
for (int k = 0; k < celllist[i].length; k++) {
if (celllist[i][k] != null)
copy[i][k] = celllist[i][k].clone();
}
}
return copy;
}
}

N times problem while iterating through loop in Duplicate element program

import java.util.*;
public class TestClass {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
String[] val = new String[n];
scan.nextLine();
for (int i = 0; i < n; i++) {
val[i] = scan.nextLine();
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (val[i].equals(val[j])) {
System.out.println(val[i]);
}
}
}
}
}
This is a simple code for finding duplicate array value but I need an else part where it should print "No duplicate found" but the problem is as I am iterating it through a loop it's printing N times the output.
INPUT
cat
dog
frog
owl
OUTPUT
No duplicate found
you can have a check variable for example
boolean duplicatefound = false;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (val[i].equals(val[j]))
{
System.out.println(val[i]);
duplicatefound = true;
}
}
}
if(duplicatefound)
{
System.out.println("duplicate found");
}else
{
System.out.println("No Duplicated found");
}
Can we use something like this
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;
public class TestClass
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
String[] val = new String[n];
scan.nextLine();
for (int i = 0; i < n; i++)
{
val[i] = scan.nextLine();
}
boolean dups = false;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (val[i].equals(val[j]))
{
System.out.println(val[i]);
} else
{
dups = true;
}
}
}
if (dups)
{
System.out.println("no duplicate found");
}
if (findDups(val))
{
System.out.println("no duplicate found");
}
if (findDups(Arrays.asList(val)))
{
System.out.println("no duplicate found");
}
}
// different approach to avoid nested loops
public static boolean findDups(String[] arr)
{
Set<String> set = new HashSet<>();
for (String i : arr)
{
if (set.contains(i))
{
return false;
} else
{
set.add(i);
}
}
return true;
}
// Java 8 streams
public static boolean findDups(List<String> list)
{
return list.stream().filter(i -> Collections.frequency(list, i) > 1)
.collect(Collectors.toSet()).isEmpty();
}
}

Creating a Word List array that can be modified by adding and removing words

In this problem, I am attempting to begin with an array and add or remove words. My problem so far is adding words. I want to have an array String[] {"",""} and fill this up, and if a word is repeated, do nothing. So, add("computer"), add("again"), and add("computer") would result in {"computer", "again"} and give me count 3. I keep getting {"computer", "computer", "again"} remove("computer") would result in {"again", "again"} and give me count 1. Could on look at this code and help?
public class WordList {
public String[] words;
int count;
public WordList() {
count = 0;
words = new String[] {"",""};
}
public int addWord(String w) {
WordList r = new WordList();
int x = r.findWord(w);
int y = words.length;
if (x>-1) {
return count;
}
else if (x==-1) {
if (count < words.length) {
words[count] = w;
}
else if (count == words.length) {
String[] nwords = new String[words.length * 2];
for (int i = 0; i < words.length; i++) {
nwords[i] = words[i];
}
words = nwords;
words[y] = w;
}
count++;
}
return count;
}
public void removeWord(String s) {
WordList r = new WordList();
int x = r.findWord(s);
if (x == -1) {
return;
}
if (x>-1) {
for (int j=0;j<words.length;j++) {
words[j] = words[j+1];
count--;
}
}
return;
}
public int findWord(String w) {
for (int i =0;i<words.length; i++) {
if (w.equals(words[i])) {
return i;
}
}
return -1;
}
public boolean equals(WordList other) {
if (words.length != other.count) {
return false;
} else {
for (int i = 0; i < words.length; i++) {
if (words[i] != other.words[i]) {
return false;
}
}
}
return true;
}
public String toString() {
String s = "There are " + count + " word" + ((words.length == 1)?"":"s") + " in the word list:\n";
for (String w : words) {
s = s + w + "\n";
}
return s;
}
public static void main(String[] args) {
WordList wl = new WordList();
System.out.println(wl.addWord("computer"));
System.out.println(wl.addWord("abacus"));
System.out.println(wl.addWord("computer"));
wl.removeWord("computer");
}
}
First of all. Please consider Arraylist or Map.
Nevertheless i tried to keep changes to the minimal
public class WordList {
public String[] words;
int count;
public WordList() {
count = 0;
words = new String[] {"",""};
}
public int addWord(String w) {
//WordList r = new WordList();
int x = findWord(w);
int y = words.length;
if (x>-1) {
return count++;
}
else if (x==-1) {
if (count < words.length) {
words[count] = w;
}
else if (count == words.length) {
String[] nwords = new String[words.length * 2];
for (int i = 0; i < words.length; i++) {
nwords[i] = words[i];
}
words = nwords;
words[y] = w;
}
count++;
}
return count;
}
public void removeWord(String s) {
//WordList r = new WordList();
int x = findWord(s);
if (x == -1) {
return;
}
if (x>-1) {
for (int j=0;j<words.length;j++) {
if(words.length < j+1 && !words[j+1].isBlank()){
words[j] = words[j+1];
}
}
count--;
}
return;
}
public int findWord(String w) {
for (int i =0;i<words.length; i++) {
if (w.equals(words[i])) {
return i;
}
}
return -1;
}
public boolean equals(WordList other) {
if (words.length != other.count) {
return false;
} else {
for (int i = 0; i < words.length; i++) {
if (words[i] != other.words[i]) {
return false;
}
}
}
return true;
}
public String toString() {
String s = "There are " + count + " word" + ((words.length == 1)?"":"s") + " in the word list:\n";
for (String w : words) {
s = s + w + "\n";
}
return s;
}
public static void main(String[] args) {
WordList wl = new WordList();
System.out.println(wl.addWord("computer"));
System.out.println(wl);
System.out.println(wl.addWord("abacus"));
System.out.println(wl);
System.out.println(wl.addWord("computer"));
System.out.println(wl);
wl.removeWord("computer");
System.out.println(wl);
}
}
The severe ones are:
1. You are working on new instances of wordlist (r) when adding and removing which is absolutely wrong.
2. When removing word you have to check the length of word before going for j+1
You should use a Set, not an array.
That will reduce your code to:
class WordList {
private Set<String> words;
public WordList() {
words = new HashSet<>();
}
public int addWord(String w) {
words.add(w);
return words.size();
}
public void removeWord(String s) {
words.remove(s);
}
public boolean findWord(String w) {
return words.contains(w);
}
public boolean equals(WordList other) {
return this.words.equals(other.words);
}
#Override
public String toString() {
String s = "There are " + words.size() + " word" + ((words.size() == 1)?"":"s") + " in the word list:\n";
for (String w : words) {
s = s + w + "\n";
}
return s;
}
public static void main(String[] args) {
WordList wl = new WordList();
System.out.println(wl.addWord("computer"));
System.out.println(wl.addWord("abacus"));
System.out.println(wl.addWord("computer"));
wl.removeWord("computer");
}
}
Output
1
2
2

boolean allLess(int[] one,int[] two) method

so I am trying to make this method that takes in two int Arrays and returns true if each element in the first array is less than the element at the same index in the second array if the arrays are of different lengths then it will compare up to the length of the shorter array. this is what i have so far but i keep failing two j unit tests and cant figure out what is causing it. Thank you for any help in advance.
here are the two junit tests i am failing
#Test
public void testSecondLessFirstLonger() {
int[] one = { 5, 5, 5 };
int[] two = { 4 };
boolean actual = Program1.allLess( one, two );
assertFalse( "Incorrect result",actual );
}
#Test
public void testSecondLessSecondLonger() {
int[] one = { 2 };
int[] two = { 1, 0 };
boolean actual = Program1.allLess( one, two );
assertFalse( "Incorrect result",actual );
}
import java.util.Arrays;
here is the code i have so far
public class Program1 {
public static void main(String[] args)
{
int[] one = { 2 };
int[] two = { 1, 0 };
System.out.println(allLess(one, two));
}
public static boolean allLess(int[] one,int[] two)
{
if (one.length != two.length)
{
int len = 0;
if(one.length <= two.length)
{
len = one.length;
}
if(two.length < one.length)
{
len = two.length;
}
boolean[] boo = new boolean[len];
for(int i = 0; i < len; i++)
{
if(one[i] < two[i])
{
boo[i] = true;
}
else
{
boo[i] = false;
}
}
if(Arrays.asList(boo).contains(false))
{
return false;
}
else
{
return true;
}
}
for (int i = 0; i < one.length; i++)
{
if (one[i] >= two[i])
{
return false;
}
}
return true;
}
}
Perhaps you could try something like this:
public static boolean allLess(final int[] array1, final int[] array2){
for(int i = 0; i < Math.min(array1.length, array2.length); i++)
if(array1[i] >= array2[i])
return false;
return true;
}
//this way works too. did you get program 3 done yet? Its giving me issues
import java.lang.Math.*;
public class Program1 {
public static boolean allLess(int[] one, int[] two) {
if (one == null || two == null) {
return false;
}
for (int i = 0; i < Math.min(one.length, two.length); i++) {
if (two[i] <= one[i]) {
return false;
}
}
return true;
}
public static void main(String[] args) {
System.out.println(" ");
}
}

Problem in implementing Sorted List by Array in Java

There seems to be a problem in add method of the class I have written.. I want to make a SortedList using an array, but I can't figure out what the problem is. This is my code:
public class SortedList {
private Integer[] elements;
private int size;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
cap = capacity;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el)
{
if(this.isEmpty())
{
elements[0] = el;
size++;
}
else if(this.isFull())
{
this.doubleCapacity();
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
else
{
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
}
public String toString()
{
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public static void main(String[] args)
{
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(4);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
}
}
My code works if I only add 2 Integers to my list, but when I try to add the numbers 3,4,5 then I get 3,5,5...
What can be the problem? Thanks..
public class SortedList {
private Integer[] elements;
private int size=0;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
capacity = cap;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el) throws Exception{
elements[size] = el;
size++;
if(size>capacity){
throw new Exception("Size Exceeded");
}
}
public String toString()
{
sort();
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public void sort(){
for (int i=0; i <size()-1; i++) {
if (elements[i] > elements[i+1]) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}
}
public static void main(String[] args)
{
try {
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(6);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
} catch (Exception ex) {
Logger.getLogger(SortedList.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Your insertion code doesn't work.
elements[i+1] = elements[i];
elements[i] = el;
What happens to the old value of elements[i+1]?
I'd recommend the following changes to the previous solution. If you're only calling sort in toString(), your list is going to get out of order quickly in cases where you have multiple unsorted elements in a row (Now you could remove sort() from toString()). It's essentially a quick insertion sort that dies as soon as it can't make any more swaps down the list. Again, as dty suggested, a faster choice would be a binary search to find the insertion point.
public void doubleCapacity(){
capacity = capacity * 2;
Integer temp[] = new Integer[capacity];
for (int i = 0; i < size; i++){
temp[i] = elements[i];
}
elements = temp;
}
public void add(Integer el){
if(size+1>capacity){
doubleCapacity();
}
elements[size] = el;
size++;
sort();
}
public void sort(){
//Iterates down the list until it's sorted.
for (int i=size()-2; i >= 0 && (elements[i] < elements[i+1]); i--) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}

Categories

Resources