I'm working on an exercise that requires that I print 20 rolls of a die out and group repeated values in parentheses. My code below follows the pseudocode the book I'm reading says to use. I am able to group the repeated values in parentheses but the next exercise requires that I group the values that are repeated the most in parentheses.
For example:
(333)51314121(22)326(55)14
would be:
(333)51314121223265514
EDIT: If there is more than one largest group of repeated values only the first is to be grouped in parentheses.
How can I accomplish this? Many thanks in advance for any help on this.
public void run() {
Random generator = new Random();
ArrayList<Integer> a = new ArrayList<Integer>();
for (int i = 0; i < 21; i++) {
int die = generator.nextInt(6)+ 1;
a.add(die);
}
for (int j = 0; j < a.size() - 1; j++) {
if (inRun) {
if (a.get(j) != a.get(j - 1)) {
System.out.print(")");
inRun = false;
}
}
else {
if (a.get(j) == a.get(j + 1)) {
System.out.print("(");
inRun = true;
}
}
System.out.print(a.get(j));
}
if (inRun) {
System.out.print(")");
}
}
You don't really need a data structure other than an ordinary array.
You can make it O(n) by checking while inserting:
If the added number equals the previous, you increment the sequence count - if not, you reset the count.
When you increment a sequence count, check if it is bigger than the already stored max sequence count length - if it is bigger, the current sequence count becomes the max sequence count.
Check the code - some comments there to help understanding (run demo online here):
public void run() {
Random generator = new Random();
int[] a = new int[20];
int biggerSequence = 1; // starts pointing to the first char
int biggerSequenceEndIndex = 1; // starts pointing to the first char
int currentSequence = 1;
int previous = -1;
for (int i = 0; i < 20; i++) {
int die = generator.nextInt(6)+ 1;
a[i] = die;
if (die == previous) { // if inserted equals previous
currentSequence++; // increment sequence
if (currentSequence > biggerSequence) { // if it is bigger than max
biggerSequence = currentSequence; // max becomes it
biggerSequenceEndIndex = i+1;
}
} else {
previous = die;
currentSequence = 1; // reset the count
}
}
for (int i = 0; i < a.length; i++) {
if (i == biggerSequenceEndIndex-biggerSequence) { System.out.print("("); }
System.out.print(a[i]);
if (i+1 == biggerSequenceEndIndex) { System.out.print(")"); }
}
}
Example outputs:
(1)2345678901234567890
(11)345678901234567890
1(22)45678901234567890
1(22)45578901234567890
123456789012345678(99)
54(3333)43514564513551
You need to make multiple passes over the array. Go through it once and tally up how long all the runs are. Then decide what the maximum run length is. Finally, go back and print out the array, putting parentheses around runs of the maximum length.
Try something like this (exact implementation left to you):
runContents = a list containing the first random number
runLength = [1], i.e. a one element list with the number 1 in it
maxLength = 1
for each subsequent random number you want to consider {
if the last element of runContents == the next random number {
add 1 to the last element of runLength
} else {
if maxLength < the last element of runLength {
maxLength = the last element of runLength
}
append the random number to runContents
append a 1 to runLength
}
}
i = 0
while i < length(runContents) {
if runLength[i] == maxLength {
print runLength[i] copies of runContents[i] surrounded by parens
} else {
print runLength[i] copies of runContents[i]
}
}
Just try storing the number of repeated values starting at any given index. Something like:
public void run(){
Random generator = new Random();
ArrayList<Integer> a = new ArrayList<Integer>();
for (int i = 0; i < 21; i++) {//Generate your numbers
int die = generator.nextInt(6)+ 1;
a.add(die);
}
//store the number of repeats by index. (index is key, # of repeats is key)
HashMap<Integer, Integer> repeats = new HashMap<Integer, Integer>();
//This will find store the number of repeated numbers starting at any given index.
int index = 0;
repeats.put(index, 1);
for(int i = 1; i < a.size(); i++){
if(a.get(i) == a.get(index)){//Repeated values occurring
repeats.put(index, repeats.get(index) + 1);
} else {//End of a repeated sequence (even if that sequence was only 1 number long)
repeats.put(i, 1);
index = i;
}
}
//Find the index at which the maximum number of repeats occurs
int max = 0;
int startIndex = 0;
for(Integer i : repeats.keySet()){
//If the number of repeats is bigger than anything seen before
if(repeats.get(i) > max){
//Store the number of repeats and the index at which they start
max = repeats.get(i);
startIndex = i;
}
}
//print everything out
for(int i = 0; i < a.size(); i++){
if(i == startIndex)//Prints the open parenthesis before the repeats start
System.out.print("(");
System.out.print(a.get(i)); //Prints the number
if(i == startIndex + max)
System.out.print(")");//Prints the close parenthesis after the repeats end
}
}
Note that this algorithm assumes that there is only 1 repeated sequence of the maximum size. Should there be multiple that you want to keep, you'll have to store all indexes in another list. But that's a minor fix to the solution that would look like so:
ArrayList<Integer> startIndeces = new ArrayList<Integer>();
int max = 0;
for(Integer i : repeats.keySet()){
//If the number of repeats is bigger than anything seen before
if(repeats.get(i) > max){
//Store the number of repeats and the index at which they start
max = repeats.get(i);
startIndeces = new ArrayList<Integer>();
startIndeces.add(i);
} else if(repeats.get(i) == max)
startIndeces.add(i);
}
Otherwise the algorithm stores the first instance of the longest sequence.
Related
I have wrote a method for the question:
input: an array of integers
return: the length of longest consecutive integer sequence.
like: for {9,1,2,3}, return 3, cuz{1,2,3}
the method doesnt run well. hope someone could help me with debugging.
public int solution(int[] arr){
int counter = 1;
int max = arr[1];
//find the max in the array
for (int i : arr){
if (i > max){
max = i;
}
}
int[] nArr = new int[max];
for (int i : arr){
nArr[i] = i;
}
List<Integer> counters = new ArrayList<>();
for (int i = 0; i < max; i++){
if (nArr[i] == nArr[i+1] - 1){
counter++;
}else{
counters.add(counter);
counter = 1;
}
}
max = counters.get(1);
for (int i : counters){
if (i > max){
max = i;
}
}
return max; }
thanks a lot!!!
You dont need to use ArrayList... If all you want is max count of sequential integers, then try this:
int[] a = somethingBlaBla;
int counter = 0; // Stores temporary maxes
int secCounter = 0; //Stores final max
for(int j = 0; j<a.length-1; j++){ // Iterate through array
if(a[j] == a[j+1]-1){
counter++; // If match found then increment counter
if(counter > secCounter)
secCounter = counter; // If current match is greater than stored match, replace current match
}
else
counter = 0; // Reset match to accumulate new match
}
System.out.println(secCounter);
As for your method, the first thing I noticed is that max has value of greatest number in array and not the size of array. So if my array is something like {1,2,3,45,6,7,8,9}, it will throw indexOutOfBoundsException because its gonna try get 45th element in array which is not present.
Hi so I am supposed to count the number of unique elements after an array sort excluding duplicates but i'm getting the wrong output.
In in = new In(args[0]);
int[] whitelist = in.readAllInts();
Arrays.sort(whitelist);
int count = 0;
for (int i = 0; i < whitelist.length; i++) {
if (whitelist[i] == whitelist[count]) {
count++;
}
}
while (!StdIn.isEmpty()) {
int key = StdIn.readInt();
rank(key, whitelist);
}
System.out.println(count);
}
}
expected output: java InstrumentedBinarySearch tinyW.txt < tinyT.txt
65
got: 16
Did i count the number of duplicates or something?
int flag = 0;
int count = 0;
for (int i = 0; i < whitelist.length; i++) //Element to be checked for
{
for (int j=0; j< whitelist.length ; j++) //Loop that goes through the whole array
{
if (whitelist[i] == whitelist[j]) //checks if there are duplicates
{
flag++; // count
}
}
if( flag==1) //There should be only 1 instance of the element in the array and that is the element itself
{
System.out.println(whitelist[i]); //displays unique element
count++; // Keeps count
}
}
This algorithm counts how many different unique numbers there are in the array. A number appearing more than once will only count for 1. I am assuming this is what you mean, as opposed to "numbers which appear exactly once".
There is a more trivial way to do it, as proposed in another answer, but it requires a nested for-loop and therefore executes in quadratic complexity. My algorithm below attempts to solve the problem in linear time proportional to the array size.
int uniquesFound = 0;
// Assume that array is sorted, so duplicates would be next to another.
// If we find duplicates, such as 12223, we will only count its last instance (i.e. the last '2')
for (int i = 0; i < whitelist.length; i++) {
// If we are at the last element, we know we can count it
if (i != whitelist.length - 1) {
if (whitelist[i] != whitelist[i+1]) {
uniquesFound++;
}
else {
// Nothing! If they are the same, move to the next step element
}
} else {
uniquesFound++;
}
}
For instance, given the array:
{1,2,3} this will yield 3 because there are 3 unique numbers
{1,2,3,3,3,4,4,4,5} this will yield 5 because there are still 5 unique numbers
First let's take a look at your loop:
for (int i = 0; i < whitelist.length; i++) {
if (whitelist[i] == whitelist[count]) {
count++;
}
}
You should be comparing consecutive elements in the list, like whitelist[0] == whitelist[1]?, whitelist[1] == whitelist[2]?, whitelist[3] == whitelist[4]?, etc. Doing whitelist[i] == whitelist[count] makes no sense in this context.
Now you have two options:
a. Increment your counter when you find two consecutive elements that are equal and subtract the result from the total size of the array:
for (int i = 0; i < whitelist.length - 1; i++) {
if (whitelist[i] == whitelist[i + 1]) {
count++;
}
}
int result = whitelist.length - count;
b. Change the condition to count the transitions between consecutive elements that are not equal. Since you are counting the number of transitions, you need to add 1 to count in the end to get the number of unique elements in the array:
for (int i = 0; i < whitelist.length - 1; i++) {
if (whitelist[i] != whitelist[i + 1]) {
count++;
}
}
int result = count + 1;
Note that, in both cases, we loop only until whitelist.length - 1, so that whitelist[i + 1] does not go out of bounds.
I have an array:
int[] anArray = new int[6];
What if the array contained 1,4,5,4,4? How can I get the most matches? In this case 4 is the most frequent number, and there are three of them, so the function should return 3.
Or if I have 1,2,1,2,3 it should return 2.
Or if I have 4,0,1,2,3 it should return 1.
I really can't figure it out. I tried this:
public static int getCorrectMatches(int[] flowers) throws Exception {
int highest = 0;
for(int index = 0; index < 5; index++) {
int count = countMatches(flowers, index);
if(count > highest) {
highest = index;
}
}
return highest;
}
public static int countMatches(int[] array, int match) throws Exception {
int count = 0;
for(; count < array.length && array[count] == match; count++);
return count;
}
Which didn't work. I'd appreciate any help.
Iterate over the array and for each number store a counter in a hashmap where the key of the map is the number and the value is the counter that tracks the number of occurrences. The first time you encounter a new number (for which there is no key) you'll need insert a new counter. The next time you encounter that same number you simply update the existing counter with a new number.
It also wouldn't be too hard to keep a running 'most matches' number and update it each time you are updating a counter.
public static int numberOfMatches(int[] numbers) {
int mostMatches = 0;
for(int i = 0; i < numbers.length; i++) {
int matches = 0;
int holder = numbers[i];
for(int number : numbers) {
if(number == holder) {
matches++;
}
}
if(matches > mostMatches)
mostMatches = matches;
}
return mostMatches;
}
This accepts an array. It checks the length of the array, and loops for each slot.
For each slot, I create 2 variables. holder grabs the value in the slot, and we increase matches any time there is a match.
Once all possible matches have been found for that slot, it compares the amount of matches found to the highest amount of matches found so far.
for each index in array
HashMap.put(number on index i, occurrences) +=1
check biggest value in the hash map
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put(K,%20V)
Your countMatches() method is incorrect. Decouple count from the loop variable and check the equality inside the loop, instead of putting it in the loop condition. Change it to something like this:
public static int countMatches(int[] array, int match) throws Exception {
int count = 0;
for(int i=0; i< array.length ; i++){
if(array[i] == match) count++;
}
return count;
}
Also, if I were you, I'd change
for(int index = 0; index < 5; index++) {
to,
for(int index = 0; index < flowers.length; index++) {
I have to create a program that takes an array of both even and odd numbers and puts all the even numbers into one array and all the odd numbers into another. I used a for loop to cycle through all the numbers and determine if they are even or odd, but the problem I'm having is that since the numbers in the original array are random, I don't know the size of either the even or the odd array and therefore can't figure out how to assign numbers in the original array to the even/odd arrays without having a bunch of spots left over, or not having enough spots for all the numbers. Any ideas?
Try using an ArrayList. You can use
num % 2 == 0
to see if num is even or odd. If it does == 0 then it is even, else it is odd.
List<Integer> odds = new ArrayList();
List<Integer> evens = new ArrayList();
for (int i = 0; i< array.length; i++) {
if (array[i] % 2 == 0) {
evens.add(array[i]);
}
else {
odds.add(array[i]);
}
}
to convert the ArrayLists back to arrays you can do
int[] evn = evens.toArray(new Integer[evens.size()]);
(Note: untested code so there could be a few typos)
EDIT:
If you are not allowed to use ArrayLists then consider the following that just uses Arrays. It's not as efficient as it has to do two passes of the original array
int oddSize = 0;
int evenSize = 0;
for (int i = 0; i< array.length; i++) {
if (array[i] % 2 == 0) {
evenSize++;
}
else {
oddSize++;
}
}
Integer[] oddArray = new Integer[oddSize];
Integer[] evenArray = new Integer[evenSize];
int evenIdx = 0;
int oddIdx = 0;
for (int i = 0; i< array.length; i++) {
if (array[i] % 2 == 0) {
evenArray[evenIdx++] = array[i];
}
else {
oddArray[oddIdx++] = array[i];
}
}
You can do it without using arrays or any '%' Just a simple idea
input = new Scanner(System.in);
int x;
int y = 0; // Setting Y for 0 so when you add 2 to it always gives even
// numbers
int i = 1; // Setting X for 1 so when you add 2 to it always gives odd
// numbers
// So for example 0+2=2 / 2+2=4 / 4+2=6 etc..
System.out.print("Please input a number: ");
x = input.nextInt();
for (;;) { // infinite loop so it keeps on adding 2 until the number you
// input is = to one of y or i
if (x == y) {
System.out.print("The number is even ");
System.exit(0);
}
if (x == i) {
System.out.print("The number is odd ");
System.exit(0);
}
if (x < 0) {
System.out.print("Invald value");
System.exit(0);
}
y = y + 2;
i = i + 2;
}
}
Use a List instead. Then you don't need to declare the sizes in advance, they can grow dynamically.
You can always use the toArray() method on the List afterwards if you really need an array.
The above answers are correct and describe how people would normally implement this. But the description of your problem makes me think this is a class assignment of sorts where dynamic lists are probably unwelcome.
So here's an alternative.
Sort the array to be divided into two parts - of odd and of even numbers. Then count how many odd/even numbers there are and copy the values into two arrays.
Something like this:
static void insertionSort(final int[] arr) {
int i, j, newValue;
int oddity;
for (i = 1; i < arr.length; i++) {
newValue = arr[i];
j = i;
oddity = newValue % 2;
while (j > 0 && arr[j - 1] % 2 > oddity) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = newValue;
}
}
public static void main(final String[] args) {
final int[] numbers = { 1, 3, 5, 2, 2 };
insertionSort(numbers);
int i = 0;
for (; i < numbers.length; i++) {
if (numbers[i] % 2 != 0) {
i--;
break;
}
}
final int[] evens = new int[i + 1];
final int[] odds = new int[numbers.length - i - 1];
if (evens.length != 0) {
System.arraycopy(numbers, 0, evens, 0, evens.length);
}
if (odds.length != 0) {
System.arraycopy(numbers, i + 1, odds, 0, odds.length);
}
for (int j = 0; j < evens.length; j++) {
System.out.print(evens[j]);
System.out.print(" ");
}
System.out.println();
for (int j = 0; j < odds.length; j++) {
System.out.print(odds[j]);
System.out.print(" ");
}
}
Iterate through your source array twice. The first time through, count the number of odd and even values. From that, you'll know the size of the two destination arrays. Create them, and take a second pass through your source array, this time copying each value to its appropriate destination array.
I imagine two possibilities, if you can't use Lists, you can iterate twice to count the number of even and odd numbers and then build two arrays with that sizes and iterate again to distribute numbers in each array, but thissolution is slow and ugly.
I imagine another solution, using only one array, the same array that contains all the numbers. You can sort the array, for example set even numbers in the left side and odd numbers in the right side. Then you have one index with the position in the array with the separation ofthese two parts. In the same array, you have two subarrays with the numbers. Use a efficient sort algorithm of course.
Use following Code :
public class ArrayComparing {
Scanner console= new Scanner(System.in);
String[] names;
String[] temp;
int[] grade;
public static void main(String[] args) {
new ArrayComparing().getUserData();
}
private void getUserData() {
names = new String[3];
for(int i = 0; i < names.length; i++) {
System.out.print("Please Enter Student name: ");
names[i] =console.nextLine();
temp[i] = names[i];
}
grade = new int[3];
for(int i =0;i<grade.length;i++) {
System.out.print("Please Enter Student marks: ");
grade[i] =console.nextInt();
}
sortArray(names);
}
private void sortArray(String[] arrayToSort) {
Arrays.sort(arrayToSort);
getIndex(arrayToSort);
}
private void getIndex(String[] sortedArray) {
for(int x = 0; x < sortedArray.length; x++) {
for(int y = 0; y < names.length; y++) {
if(sortedArray[x].equals(temp[y])) {
System.out.println(sortedArray[x] + " " + grade[y]);
}
}
}
}
}
I'm completely new in Java. I am writing an Android game, and I need to generate an array of int arrays that contains all possible sums (excluding combinations that contains number 2 or is bigger than 8 numbers) that add up to a given number.
For example:
ganeratePatterns(5) must return array
[patternNumber][summandNumber] = value
[0][0] = 5
[1][0] = 1
[1][1] = 1
[1][2] = 1
[1][3] = 1
[1][4] = 1
[2][0] = 3
[2][1] = 1
[2][2] = 1
[3][0] = 4
[3][1] = 1
I already try to do this like there Getting all possible sums that add up to a given number
but it's very difficult to me to make it like this http://introcs.cs.princeton.edu/java/23recursion/Partition.java.html
Solution
int n = 10;
int dimension = 0;
//First we need to count number of posible combinations to create a 2dimensionarray
for(List<Integer> sumt : new SumIterator(n)) {
if(!sumt.contains(2) && sumt.size() < 9) {
dimension++;
}
}
int[][] combinationPattern = new int[dimension][];
int foo = 0;
for(List<Integer> sum : new SumIterator(n)) {
if(!sum.contains(2) && sum.size() < 9) {
System.out.println(sum);
combinationPattern[foo] = toIntArray(sum);
foo++;
}
}
It's work not 100% correctly, and very pretty, but it is enough for my game
I have used SumIterator class from here SumIterator.class
I have to changed this code for(int j = n-1; j > n/2; j--) { to this for(int j = n-1; j >= n/2; j--) { because old version doesn't return all combinations (like [5,5] for 10)
And I used toIntArray function. I have founded hare on StackOverflow, but forget a link so here it's source:
public static int[] toIntArray(final Collection<Integer> data){
int[] result;
// null result for null input
if(data == null){
result = null;
// empty array for empty collection
} else if(data.isEmpty()){
result = new int[0];
} else{
final Collection<Integer> effective;
// if data contains null make defensive copy
// and remove null values
if(data.contains(null)){
effective = new ArrayList<Integer>(data);
while(effective.remove(null)){}
// otherwise use original collection
}else{
effective = data;
}
result = new int[effective.size()];
int offset = 0;
// store values
for(final Integer i : effective){
result[offset++] = i.intValue();
}
}
return result;
}
This is not the most beautiful code, but it does what you would like, having modified the code you referenced. It is also quite fast. It could be made faster by staying away from recursion (using a stack), and completely avoiding String-to-integer conversion. I may come back and edit those changes in. Running on my pretty outdated laptop, it printed the partitions of 50 (all 204226 of them) in under 5 seconds.
When partition(N) exits in this code, partitions will hold the partitions of N.
First, it builds an ArrayList of string representations of the sums in space-delimited format (example: " 1 1 1").
It then creates a two-dimensional array of ints which can hold all of the results.
It splits each String in the ArrayList into an array of Strings which each contain only a single number.
For each String, it creates an array of ints by parsing each number into an array.
This int array is then added to the two-dimensional array of ints.
Let me know if you have any questions!
import java.util.ArrayList;
public class Partition
{
static ArrayList<String> list = new ArrayList<String>();
static int[][] partitions;
public static void partition(int n)
{
partition(n, n, "");
partitions = new int[list.size()][0];
for (int i = 0; i < list.size(); i++)
{
String s = list.get(i);
String[] stringAsArray = s.trim().split(" ");
int[] intArray = new int[stringAsArray.length];
for (int j = 0; j < stringAsArray.length; j++)
{
intArray[j] = Integer.parseInt(stringAsArray[j]);
}
partitions[i] = intArray;
}
}
public static void partition(int n, int max, String prefix)
{
if(prefix.trim().split(" ").length > 8 || (prefix + " ").contains(" 2 "))
{
return;
}
if (n == 0)
{
list.add(prefix);
return;
}
for (int i = Math.min(max, n); i >= 1; i--)
{
partition(n - i, i, prefix + " " + i);
}
}
public static void main(String[] args)
{
int N = 50;
partition(N);
/**
* Demonstrates that the above code works as intended.
*/
for (int i = 0; i < partitions.length; i++)
{
int[] currentArray = partitions[i];
for (int j = 0; j < currentArray.length; j++)
{
System.out.print(currentArray[j] + " ");
}
System.out.println();
}
}
}