I'm trying to create a list of 20 integers between 0 and 26 (so in the 1-25 range) that does not repeat as a part of an assignment. I thought I had it figured out, but the program keeps looping over and over without ever ending. Can anyone help me out?
import java.util.Random;
public class prog433a
{
public static void main(String args[])
{
Random r = new Random();
int[] list = new int[20];
for (int k = 0; k < list.length; k++)
{
boolean notADupe = false;
while (notADupe == false)
{
list[k] = r.nextInt(25) + 1;
for (int j = 0; j < list.length; j++)
{
if (list[j] == list [k] && j != k)
{
notADupe = true;
}
else
{
notADupe = false;
break;
}
}
System.out.println(list[k]);
}
}
}
}
EDIT: This is different from the other question because I am trying to figure out how to check for uniqueness using the methods that I am allowed to use in my assignment (essentially, the ones I'm already using in the code).
I think you've reversed the condition out there. Inside if, you should set notADup to false, rather than true. However, I would make the variable isDup instead, and change the while loop accordingly.
One more suggestion: instead of while (notADupe == false), you should just use while (!notADupe). Never compare boolean variables like that. It might surprise you at times.
So to solve your issue, just change your if-else block to:
if (list[j] == list [k] && j != k) {
notADupe = false;
break;
} else {
notADupe = true;
}
BTW, your solution is a bit complex. For every element, you are iterating over whole array to find duplicate. Rather I would suggest you to maintain a Set<Integer> storing the already seen numbers, and check in that every randomly generated number. If present, skip it and re-generate.
Pseudo code would look something like this:
arr = [] // Your list array, initialize to size 20
seen = [] // A Set
for i from 1 -> arr.length
num = rand.nextInt(25) + 1
while seen contains num
num = rand.nextInt(25) + 1
seen.add(num)
arr[i] = num
Related
I have an atomic integer array of size 10. I am using this array to organize numbers 1-10 sent in by threads. This 1-10 will eventually be able to change to be a range of numbers larger than 10 and the list is to contain the 10 greatest numbers in that range. I can see the numbers going into the loops and recognizing that they are greater than a number currently there. However, there is never more than 2 numbers in the array when it is printed out. I have tried to trace my code in debug mode, however, it looks as if it is working as intended to me. I feel like there may be a simple error to my logic? I am completely sure all values are entering in the function as I have triple checked this. I start at the end of the array which should contain the highest value and then swap downwards once the slot has been determined. I would appreciate the assistance. This is just a simple experiment I am doing in order to grasp the basics before I try to tackle a homework assignment.
Here an example of my code:
public class testing{
static AtomicIntegerArray maxList = new AtomicIntegerArray(10);
final static int n = 10;
static void setMax(int value)
{
for(int i = 9; i >= 0; i--)
{
if(value > maxList.get(i))
{
int temp = maxList.get(i);
maxList.set(i,value);
if(i == 0)
{
maxList.set(i, value);
}
else
{ for(int j = i-1; j > 0; j--)
{
maxList.set(j, temp);
temp = maxList.get(j-1);
}
}
break;
}
}
public static void main(String[] args)
{
for (int i = 0; i < n; i++)
{
setMax(i);
}
}
}
Here is an example of how it is being called:
Brooke, there is a small bug in your 'j' loop. You had saved the state of a variable (temp), however your logic in the j loop lost the state. This new logic preserves the state of the previous element in the list.
Try this:
for (int j = i - 1; j >= 0; j--) {
int t2 = maxList.get(j);
maxList.set(j, temp);
temp = t2;
}
I would like to use list.negativeNumbers(); to call out the part of a code, which counts how many negative numbers are in a list.
public void negativeNumbers(){
int negative = 0;
for (int i = 0; i <= size; i++){
if (i < 0) {
negative = negative + 1;
}
System.out.println("There are "+ negative +" negative elements in the list!");
}
}
Can you help me in creating a method, that could count negative numbers in the list the correct way?
public void negativeNumbers(){
int negative = 0;
for (int i = 0; i <= size; i++){
if (i < 0) {
negative = negative + 1;
}
System.out.println("There are "+ negative +" negative elements in the list!");
}
}
You will learn better by working out the solution for yourself.
Your code as presented is a good start but lacks:
a defined list of values to test.
a definition of the size of the list (use list.size()).
proper indexing of the list to access values to test (use list.get(i) or list[i]).
a test of each element in the list to determine its negativity. Your code tests whether the list increment variable is < 0.
negative = negative + 1 is ok, but simpler to write ++negative.
Here's a simple example:
import java.util.ArrayList;
public class negnum {
public static void main(String [] args) {
ArrayList<Integer> nums = new ArrayList();
nums.add(0);
nums.add(10);
nums.add(-10);
nums.add(20);
nums.add(-20);
nums.add(30);
nums.add(-30);
nums.add(40);
nums.add(-40);
nums.add(50);
int negs = 0;
for (int i = 0; i < nums.size(); i++){
int n = nums.get(i);
if (n < 0) {
++negs;
System.out.println(n);
}
}
System.out.println(negs +" negatives");
}
}
c:\dev>java negnum
-10
-20
-30
-40
4 negatives
If it is a list of integers you should not be doing "i < 0" but rather the number at index of i. If you were to do that, you would also want to do "< size" rather than "<= size" or else you would run into an IndexArrayOutOfBounds.
It depends on how your double linked list is implemented, but if it extends the normal List<Integer> interface it would look like:
final Integer ZERO = Integer.valueOf(0);
int countNegativeElements() {
return stream().filter(MyList::isNegative).count();
}
static boolean isNegative(Integer i) {
return i.compareTo(ZERO) < 0;
}
with streams. More traditionally with an collection for-each (or an iterator for-each):
int countNegativeElements() {
int count = 0;
for(Integer i : this) { // or iterator()
if (isNegative(i)) count++;
}
return count;
}
This does not expect concurrent modifications and is optimized for collections where iterating is the fastest access. If you have a simple type list then you can replace isNegative with a simple < 0.
This article here talks about different ways to iterate a collection.
In my code I assumed you will add the method directly to your list implementation class. Replace this or this.iterator() or this.stream() with your actual list instance if it is external.
Update:
I just saw your link to the actual linked list you are using, this would look like this (hand made iteration):
int countNegativeElements() {
Node n = start;
int count = 0;
while(n != null) {
if (n.getData() < 0) count++;
n = n.getLinkNext();
}
return count;
}
Using null since there is no hasLinkNext() which would be typical for homework :)
I don't think it is a particular good idea to work with implementations which do not fit in the Collections framework, but maybe it is required to keep the lessons simple.
I'm a pretty basic programmer and I'm coding a 'Master-mind' style guessing game program.
Now the part I'm stuck with is that I want to go through an array and increase the pointer when I come across a specific number.
Now thats pretty easy and stuff, but what I want to do is ONLY increase the counter if the number is encountered for the first time. So, for example if there are two numbers (189, 999), I want the counter to increase only once, instead of 3 times, which is what my code is doing. I know why its doing that, but I can't really figure out a way to NOT do it (except maybe declaring an array and putting all the repeated numbers in there and only incrementing it if none of the numbers match, but that's super inefficient) Here's my code:
for (int i = 0; i < mString.length(); i++) {
for (int j = 0; j < nString.length(); j++) {
if (mString.charAt(i) == nString.charAt(j)) {
correctNumbers++;
}
}
}
Thanks for taking the time to read! I'd prefer it if you wouldn't give me a direct answer and just point me in the right direction so I can learn better. Thanks again!
Your question is quite unclear. I suppose 989 and 999 will return 1. Because you only deal with number, so the solution is:
Create a boolean array with 9 element, from 0-9, named isChecked
Initialize it with false.
Whenever you found a matching number, say 9, turn the boolean element to true, so that you don't count it again (isChecked[9] = true).
Here is the code:
var isChecked = [];
function resetArray(input) {
for (var i = 0; i < 10; i++) {
input[i + ''] = false;
}
}
resetArray(isChecked);
var firstNumber = '989',
secondNumber = '999',
correctNumbers = 0,
fNum, sNum;
for (var i = 0; i < firstNumber.length; i++) {
fNum = firstNumber.charAt(i);
// Skip already checked numbers
if (isChecked[fNum]) {
continue;
}
for (var j = 0; j < secondNumber.length; j++) {
sNum = secondNumber.charAt(j);
if (fNum == sNum && !isChecked[sNum]) {
correctNumbers++;
isChecked[sNum] = true;
}
}
}
console.log(correctNumbers);
Tested on JSFiddle.
If you find anything unclear, feel free to ask me :)
(except maybe declaring an array and putting all the repeated numbers in there and only incrementing it if none of the numbers match, but that's super inefficient)
That approach is a good one, and can be made efficient by using a HashSet of Integers. Everytime you encounter a common digit, you do a contains on the set to check for that digit (gets in HashSets are of constant-time complexitiy - O(1), i.e. super quick), and if it's present in there already, you skip it. If not, you add it into the set, and increment your correctNumbers.
I believe this would help
int found=0; for (int i = 0; i < mString.length(); i++) {
for (int j = 0; j < nString.length(); j++) {
if (mString.charAt(i) == nString.charAt(j)) {
if(found==0){
correctNumbers++;
}
}
}
}
You could try making another 1D array of
int size = nstring.length() * mstring.length();
bool[] array = new bool[size];`
and then have that store a boolean flag of whether that cell has been updated before.
you would find the unique index of the cell by using
bool flag = false
flag = array[(i % mString.length()) + j)];
if(flag == true){
<don't increment>
}else{
<increment>
array[(i % mString.length()) + j)] = true;
}
you could also do this using a 2d array that basically would act as a mirror of your existing table:
bool[][] array = new bool[mstring.length()][nString.length()];
Why not just use the new stream api? Then it's just that:
Arrays.stream(mString).flatMapToInt(s -> s.chars()).distinct().count();
I'll explain:
Arrays.stream(mString) -> Create stream of all strings.
flatMapToInt -> create single concatenated stream from many IntStreams
s -> s.chars() -> Used above to create streams of characters (as ints)
distinct -> remove all duplicates, so each character is counted only once
count -> count the (unique) characters
if it's in ascending order I need to print "Ascending".
And if otherwise, print "Otherwise".
int [] a = new int[args.length];
for (int i = 0; i < args.length; i++)
{
a[i] = Integer.parseInt(args[i]);
}
if (a[0] <= args.length || a[0] == a[0])
{
System.out.println("Ascending");
}
else
{
System.out.println("Otherwise");
}
You seem to be having a lot more trouble with this exercise than you should. So I'll only give a hint, since this looks like homework: You should make n-1 comparisons in order to determine the order. Do that using a for loop.
To clarify: the code you presented does not contain a for loop that compares numbers, and does some comparisons that have nothing to do with verifying order of the numbers.
Hints:
The following two comparisons don't do anything useful: a[0] <= args.length and a[0] == a[0].
You need to use a loop.
For one, the expression a[0] == a[0] will always evaluate to true, meaning that your current code will always enter the first condition and print "Ascending".
For another, you can't establish that a list of n elements is in ascending order without some kind of iteration. You need to use a loop or recursion to check your array's elements against each other.
Try this code
public class Ascending
{
public static void main(String[] args)
{
int [] a = new int[args.length];
boolean otherwise = false;
for (int i = 0; i < args.length; i++)
{
a[i] = Integer.parseInt(args[i]);
}
for(int i=1;i<a.length;i++){
if(a[i-1]>a[i]){
otherwise = true;
}
}
if (!otherwise)
{
System.out.println("Ascending");
}
else
{
System.out.println("Otherwise");
}
}
}
I'm making an program for class that calls for the program to create 6 randomly generated integers in the range 1-40 and put them into an array. The integers have to be unique so there can't be a situation where a number certain number repeats. The array is then passed onto another method that sorts the array in ascending order. My problem is that I can't get my code to generate 6 unique numbers. My code is as follows:
private static void getComputer(int computerNumbers, int[] cN)
{
Random randomNumbers = new Random();
for (int i = 0; i < computerNumbers;)
{
int computerStored = randomNumbers.nextInt(39)+1;
if (computerStored == cN[0] || computerStored == cN[1] || computerStored == cN[2] ||
computerStored == cN[3] || computerStored == cN[4] || computerStored == cN[5])
continue;
else
computerStored = cN[i];
i++;
}
}
The above block of code outputs an array of 0,0,0,0,0,0. I just can't find out why. Any help would be much appreciated. Thank you.
Just for clarification, I know how to do a basic randomgenerator.
private static void getComputer(int computerNumbers, int[] cN)
{
Random randomNumbers = new Random();
for (int i = 0; i < computerNumbers; i++)
cN[i] = randomNumbers.nextInt(39)+1;
}
You probably meant
cN[i] = computerStored;
Note also that there are three issues with this code: You're passing in the size of the array, which is bad form in Java, you can never get zero (which is technically not a bug in this case since you're dealing with just 1-40), and your conditional is really unwieldy. Instead, I'd do this:
for(int i = 0; i < cN.length;) {
int candidate = randomNumbers.nextInt(39) + 1;
// actually, I'd either move this into another method or use a `Set` in the first place
boolean duplicate = false;
for(int j = 0; j < i || !duplicate; j++)
if(candidate == cN[j])
duplicate = true;
if(!duplicate)
cN[i++] = candidate;
}
I would approach this in a different way:
create a list of integers 1-40
shuffle them
create an array from the first 6 elements
Like this:
List<Integer> list = new ArrayList<>(40);
for (int i = 1; i < 41; i++)
list.add(i);
Collections.shuffle(list);
int[] cN = new int[6];
for (int i = 0; i < cN.length; i++)
cN[i] = list.get(i);
The advantage of this approach is you don't have to deal with the issue of duplicates, and it makes use of the JDK to do the randomizing.