How to find repeating sequence of Integers in an array of Integers? - java

How to find repeating sequence of Integers in an array of Integers?
00 would be repeating, so would 123123, but 01234593623 would not be.
I have an idea to how to do this, but it is blurry in my mind, and my implementation doesn't go far due to this.
My idea was
Offset by a certain amount each time going through a for loop
Loop through inside of that and compare chunks of numbers by that offset
In Java, I got this far:
String[] p1 = new String[nDigitGroup];
String[] p2 = new String[nDigitGroup];
for (int pos = 0; pos < number.length - 1; pos++)
{
System.out.println("HERE: " + pos + (nDigitGroup - 1));
int arrayCounter = -1;
for (int n = pos; n < pos + nDigitGroup ; n++)
{
System.out.printf("\nPOS: %d\nN: %d\n", pos, n);
arrayCounter++;
p1[arrayCounter] = number[n];
System.out.println(p1[arrayCounter]);
}
pos += nDigitGroup;
arrayCounter = -1;
System.out.println("SWITCHING");
for (int n = pos; n < pos + nDigitGroup ; n++)
{
System.out.printf("\nPOS: %d\nN: %d\n", pos, n);
arrayCounter++;
p2[arrayCounter] = number[n];
System.out.println(p2[arrayCounter]);
}
if (p1[0].equals(p2[0]) && p1[1].equals(p2[1])) System.out.println("MATCHING");
}
When ran with these arguments:
repeatingSeqOf(2, new String[] {"1", "2", "3", "4", "5", "6", "7", "7" });
I am correctly filling the section arrays, but it breaks on an index out of bounds exception.

#MiljenMikic answer's is great, especially since the grammar isn't actually regular. :D
If you want to do it on an array in general, or want to understand it, this does pretty much exactly what the regex does:
public static void main(String[] args) {
int[] arr = {0, 1, 2, 3, 2, 3}; // 2, 3 repeats at position 2.
// for every position in the array:
for (int startPos = 0; startPos < arr.length; startPos++) {
// check if there is a repeating sequence here:
// check every sequence length which is lower or equal to half the
// remaining array length: (this is important, otherwise we'll go out of bounds)
for (int sequenceLength = 1; sequenceLength <= (arr.length - startPos) / 2; sequenceLength++) {
// check if the sequences of length sequenceLength which start
// at startPos and (startPos + sequenceLength (the one
// immediately following it)) are equal:
boolean sequencesAreEqual = true;
for (int i = 0; i < sequenceLength; i++) {
if (arr[startPos + i] != arr[startPos + sequenceLength + i]) {
sequencesAreEqual = false;
break;
}
}
if (sequencesAreEqual) {
System.out.println("Found repeating sequence at pos " + startPos);
}
}
}
}

You can always play with regular expressions to achieve a desired result. Use the regex backreference and combine it with the greedy quantifier:
void printRepeating(String arrayOfInt)
{
String regex = "(\\d+)\\1";
Pattern patt = Pattern.compile(regex);
Matcher matcher = patt.matcher(arrayOfInt);
while (matcher.find())
{
System.out.println("Repeated substring: " + matcher.group(1));
}
}

The answer posted by #AdrianLeonhard is perfectly working. But if I have a sequence of
0, 1, 2, 3, 4, 3, 5, 6, 4, 7, 8, 7, 8
many might be wondering on how to get all the repeated numbers from the array.
So, I wrote this simple logic which prints all the repeated numbers with their positions
int[] arr = {0, 1, 2, 3, 4, 3, 5, 6, 4, 7, 8, 7, 8};
for(int i=0; i<arr.length;i++){
for(int j=i+1; j<arr.length;j++){
if(arr[i] == arr[j]){
System.out.println("Number: "+arr[i]+" found repeating at position: "+i+" , repeated at position "+j);
}
}
}

Try this:
string lookIn = "99123998877665544123";
// above has length of 20 (in positions 0 through 19)
int patternLength = 3;
// want to search each triple of letters 0-2, 1-3, 2-4 ... 17-19
// however since there must be 3 chars after the 3-char pattern
// we only want to search the triples up to 14-16 (20 - 3*2)
for (int i=0; i <= lookIn.Length - patternLength * 2; i++) {
string lookingFor = lookIn.Substring(i, patternLength);
// start looking at the pos after the pattern
int iFoundPos = lookIn.IndexOf(lookingFor, i + patternLength);
if (iFoundPos > -1) {
string msg = "Found pattern '" + lookingFor
+ "' at position " + i
+ " recurs at position " + iFoundPos;
}
}
// of course, you will want to validate that patternLength is less than
// or equal to half the length of lookIn.Length, etc.
EDIT: improved and converted to javascript (from C# ... oops, sorry about that...)
function testfn() {
var lookIn = "99123998877665544123";
// above has length of 20 (in positions 0 through 19)
var patternLength_Min = 2;
var patternLength_Max = 5;
if (patternLength_Max > (lookIn.length / 2)
|| patternLength_Max < patternLength_Min
|| patternLength_Min < 1) {
alert('Invalid lengths.')
}
var msg = "";
for (var pLen = patternLength_Min; pLen <= patternLength_Max; pLen++) {
for (var i = 0; i <= lookIn.length - pLen * 2; i++) {
var lookingFor = lookIn.substring(i, i + pLen);
// start looking at the pos after the pattern
var iFoundPos = lookIn.indexOf(lookingFor, i + pLen);
if (iFoundPos > -1) {
msg = msg + "Found '" + lookingFor
+ "' at pos=" + i
+ " recurs at pos=" + iFoundPos + "\n";
;
}
}
}
alert(msg);
}
The message box displays the following:
Found '99' at pos=0 recurs at pos=5
Found '12' at pos=2 recurs at pos=17
Found '23' at pos=3 recurs at pos=18
Found '123' at pos=2 recurs at pos=17

Related

How can this solution to an altPairs problem using String variables be explained?

Task
Given a string, return a string made of the chars at indexes 0,1, 4,5, 8,9 ... so "kittens" yields "kien".
Example test-cases:
altPairs("kitten") → "kien"
altPairs("Chocolate") → "Chole"
altPairs("CodingHorror") → "Congrr"
Solution (to be explained)
String result = "";
/* I understand that I am running
i by 4 to hit 0, 4, 8,12 and all
following ints until the string length ends.*/
for (int i=0; i<str.length(); i +=
4) {
/* why is using
i + 2 is the best way to solve.
this. How is it applicable when
i+1 seems to be 1,
5, 9, 13 etc.*/
int end = i + 2;
if (end > str.length()) {
end = str.length();
}
result = result +
str.substring(i, end);
}
return result;
}
You are complicating it. It can be as simple as:
StringBuilder sb = new StringBuilder();
String str = "CodingHorror";
for (int i = 0; i < str.length(); i += 4) {
sb.append(str.charAt(i));
if (i + 1 < str.length()) {
sb.append(str.charAt(i + 1));
}
}
System.out.print(sb.toString()); // Congrr
Always use a StringBuilder when manipulating Strings inside a loop. StringBuilder vs String concatenation in toString() in Java

USACO Training milking time (longest non-milking time) - java

I'm having trouble with Usaco training gate's milking time problem (aka milk2). My code works for the first few problems, but then doesn't work for one of the cases.
The problem is here:http://jeremiahflaga.blogspot.com/2011/09/milking-cows-programming-problem-from.html
The case that doesn't work is: [1, 2] [3, 4] [5, 6] [7, 8] [9, 10] [11, 12] [13, 14] [15, 16] [17, 18] [19, 20] [1, 20]
I think it is because of the last [1, 20], and it makes my code not work as I don't think I'm managing the merging correctly, but I've tried for some time and ended up making the code worse.
import java.io.*;import java.util.*;
public class milk2 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("milk2in.txt"));
PrintWriter pw = new PrintWriter(new File("milk2.out"));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
String line = "";
int milkInterval = 0;
int largestMilkInterval = 0;
int noMilkInterval = 0;
int largestNoMilkInterval = 0;
milkingTime[] times = new milkingTime[N];
for (int i = 0; i < times.length; i++) {
st = new StringTokenizer(br.readLine());
milkingTime mt = new milkingTime(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
times[i] = mt;
}
System.out.println(Arrays.toString(times));
for (int i = 0; i < times.length - 1; i++) {
noMilkInterval = 0;
if (times[i].getEnd() >= times[i + 1].getStart()) {
if (times[i].getStart() > times[i + 1].getStart()) {
milkInterval += times[i + 1].getEnd() - times[i + 1].getStart();
} else {
milkInterval += (times[i].getEnd() - times[i].getStart()) + (times[i + 1].getEnd() - times[i + 1].getStart());
}
System.out.println("Milk Interval: " + milkInterval);
} else {
milkInterval += (times[i].getEnd() - times[i].getStart());
if (milkInterval > largestMilkInterval) {
largestMilkInterval = milkInterval;
}
milkInterval = 0;
noMilkInterval += times[i + 1].getStart() - times[i].getEnd();
System.out.println("No milk interval: " + noMilkInterval);
}
if (noMilkInterval > largestNoMilkInterval) {
largestNoMilkInterval = noMilkInterval;
}
if (milkInterval > largestMilkInterval) {
largestMilkInterval = milkInterval;
}
}
if (times.length == 1) {
largestMilkInterval = times[0].getEnd() - times[0].getStart();
largestNoMilkInterval = 0;
}
System.out.println("Largest Milk Interval: " + largestMilkInterval);
System.out.println("Largest no milk Interval: " + largestNoMilkInterval);
// pw.println(largestMilkInterval + " " + largestNoMilkInterval);
// pw.close();
}
}
class milkingTime {
private int start;
private int end;
public milkingTime(int s, int e) {
start = s;
end = e;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public String toString() {
return "Start: " + start + " End: " + end;
}
}
I also wonder if my code is just completely wrong, and this is not the correct direction of solving this problem.
Your solution seems wrong.
The main mistake is an assumption you apparently made, that you can find all important correlations between given intervals in a single pass along the table. Alas, the problem formulation makes no guarantee the intervals are given in any specific order. It even specifically mentions there are several 'farmers' milking – so their repective schedules may make a total input unordered when concatenated, even if each schedule is ordered. This is a case in your example data, which contains an ordered run of ten intervals
[1, 2] [3, 4] ... [19, 20]
and then another single-interval run
[1. 20]
which covers the former.
To handle that, I'd recommend sorting the data by a start time of intervals:
[1, 2] [1, 20] [3, 4] ... [19, 20]
Every two intervals with the same start time overlap, and now they sit in a contiguous block of the array, so we can easily find them. Additionally, an i-th interval overlaps some further k-th interval (with i less than k) if, and only if, the i-th one ends at the same time or later than the k-th one starts.
This is how I would merge them:
int curr = 0; // the interval to receive a merge
int next = 1; // the interval to be possibly merged into current
while (next < N)
{
if (times[curr].getEnd() >= times[next].getStart()) // overlapping?
{
times[curr].expandTo( times[next].getEnd() ); // merge to the current
}
else
{
++ curr; // finished merging to current
if (curr != next) // some items got merged
times[curr] = times[next]; // shift further items to emptied space
}
++ next;
}
newN = curr + 1; // number of separate intervals after all merges
Thanks to prior sorting we know the k-th interval can't start before the i-th one if i<k so the single condition reliably indicates all overlaps.
Of course the expandTo method in the milkingTime class must increase the end time to cover the given value:
class milkingTime {
.....
public void expandTo(int targetTime)
{
if (getEnd() < targetTime) {
setEnd(targetTime);
}
}
}
Now finding the longest interval and the longest gap is straight forward:
int longestInterval = 0;
for (int i = 0; i < newN; ++ i) {
if (times[i].getLength() > longestInterval)
longestInterval = times[i].getLength();
}
int longestGap = 0;
for (int i = 1; i < newN; ++ i) {
int gap = times[i].getStart() - times[i - 1].getEnd();
if (gap > longestGap)
longestGap = gap;
}

How can I seperate an array into different 'mags'

I have this project that I have been working on, but I'm a bit rusty so I could use some help to figure out this part.
The main jizt of my project, is that I want to be able to fire a gun at a target and have the target analyze my data.
Before I even start on this, I did some research to find out if anyone else had done this before, and turns out a company in USA have done it, but in a different way than what I imagined..
This is not meant as a business idea, just a fun project for my self :)
Now here is my issue, I ofcourse made a "prototype" without the gun, and without the targets.
All text in Java to see if I could make this work.
I researched a bit since I was rusty (and still am), and figured out most of the problems I faced.
The part that has me stuck is at the very end of it, I have an array for all the shots but I want to divide this array into multiple arrays with the size of the magazine capacity.
How would I accomplish this?
Unfortunately I don't save my code, if I chose to delete it, so my scraps are long gone, but I have tried a few things that came to mind and for several days I havn't been able to figure this one out..
I tried with nested for loops, then I tried again but with nested for loops in a while loop, and I probably tried a few different things aswell.
if (hasrun == true) {
//OUTPUT
ms(2);
System.out.print("You shot the following:");
nl(1);
int counter = 0;
int i = 0;
while (sf > magcap) {
sf-=magcap;
mnm++;
}
while (counter <= mnm) {
System.out.print("Mag " + mn + ": ");
for (i+=0; i < magcap; i++) {
System.out.print(shots[i] + " ");
}
counter++;
mn++;
nl(1);
}
Just to clarify some things in my code here, I know this isn't the cleanest code, I'm not going for clean, and I know I don't need half of my functions (methods), but I did them to practice so they're there. Any help would be greatly appreciated with solving my problem tho! :)
If you want to have a look at all of my code for this project, head over to pastebin
You can use Guava to do it easily,
int[] x = {1,2,3,4,5,6};
int splitSize = 3;
List<Integer> list = IntStream.of(x).boxed().collect(Collectors.toList());
//partition
List<List<Integer>> partitioned = Lists.partition(list, splitSize);
//result: [[1,2,3], [4,5,6]]
Using System.arraycopy:
import java.util.Arrays;
public class Testing {
// static int[] input = {1,2,3,4,5,6}; // testdata
static int[] input = {1,2,3,4,5,6,7}; // testdata
// static int[] input = {1,2,3,4,5,6,7,8}; // testdata
static int magSize = 3; // testdata
// static int magSize = 5; // testdata
public static void main(String[] args) {
// int resultSize = (int) Math.ceil((double) input.length / magSize);
int resultSize = input.length % magSize == 0 ?
input.length/magSize :
input.length/magSize + 1;
int[][] result = new int[resultSize][magSize];
for (int i = 0; i < resultSize; i++) {
System.arraycopy(input, // src
i*magSize, // srcPos
result[i], // dest
0, // destPos
(i + 1) * magSize < input.length ?
magSize :
input.length - i*magSize); // length
}
System.out.println("Original : " + Arrays.toString(input));
System.out.println("Result : " + Arrays.deepToString(result));
/*
prints:
Original : [1, 2, 3, 4, 5, 6, 7]
Result : [[1, 2, 3], [4, 5, 6], [7, 0, 0]]
*/
}
}
I figured it somewhat out, here is what I did. Not quite implemented yet, but this worked with an array.
// OUTPUT
while (sf >= magcap) {
sf -= magcap;
mn++;
}
ms(2);
System.out.println(mn + " mags and " + sf + " shots fired");
nl(2);
for (int i = 0; i < mn; i++) {
from = magcap * magcounter - magcap;
to = magcap * magcounter;
System.out.print("Mag " + magcounter + ": ");
for (int j = from; j < to - 1; j++) {
System.out.print(shots[j] + ", ");
}
System.out.print(shots[to - 1] + ".");
magcounter++;
nl(1);
}
// PRINT THE REST
if (sf >= 1) {
from = magcap * magcounter - magcap;
to = magcap * magcounter;
if (sf == 1) {
System.out.print("Mag " + magcounter + ": ");
System.out.print(shots[from] + ".");
} else {
System.out.print("Mag " + magcounter + ": ");
for (int i = 0; i < sf - 1; i++) {
System.out.print(shots[from + i] + ", ");
}
from += sf -1;
System.out.print(shots[from] + ".");
}
}
The output is
1 2 3 4 5 6 7 8 9 10
3 mags fired and 1 shots fired
Mag 1: 1 2 3
Mag 2: 4 5 6
Mag 3: 7 8 9
Mag 4: 10

How to Shrink array to specified length in java keeping elements uniformaly distributed?

I have source array, and I want to generate new array from the source array by removing a specified number of elements from the source array, I want the elements in the new array to cover as much as possible elements from the source array (the new elements are uniformly distributed over the source array) and keeping the first and last elements the same (if any).
I tried this :
public static void printArr(float[] arr)
{
for (int i = 0; i < arr.length; i++)
System.out.println("arr[" + i + "]=" + arr[i]);
}
public static float[] removeElements(float[] inputArr , int numberOfElementToDelete)
{
float [] new_arr = new float[inputArr.length - numberOfElementToDelete];
int f = (inputArr.length ) / numberOfElementToDelete;
System.out.println("f=" + f);
if(f == 1)
{
f = 2;
System.out.println("f=" + f);
}
int j = 1 ;
for (int i = 1; i < inputArr.length ; i++)
{
if( (i + 1) % f != 0)
{
System.out.println("i=" + i + " j= " + j);
if(j < new_arr.length)
{
new_arr[j] = inputArr[i];
j++;
}
}
}
new_arr[0] = inputArr[0];
new_arr[new_arr.length - 1] = inputArr[inputArr.length - 1];
return new_arr;
}
public static void main(String[] args)
{
float [] a = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
a = removeElements(a, 6);
printArr(a);
}
I have made a test for(removeElements(a, 5) and removeElements(a, 4) and removeElements(a, 3)) but removeElements(a, 6); gave :
arr[0]=1.0
arr[1]=3.0
arr[2]=5.0
arr[3]=7.0
arr[4]=9.0
arr[5]=11.0
arr[6]=13.0
arr[7]=15.0
arr[8]=0.0
arr[9]=16.0
the problem is (arr[8]=0.0) it must take a value ..
How to solve this? is there any code that can remove a specified number of elements (and keep the elements distributed over the source array without generating zero in some elements)?
EDIT :
examples :
removeElements(a, 1) ==> remove one element from the middle (7) {1,2,3,4,5,6,7,9,10,11,12,13,14,15,16}
removeElements(a, 2) ==> remove two elements at indexes (4,19) or (5,10) or (4,10) (no problem)
removeElements(a, 3) ==> remove three elements at indexes (4,9,14) or (4,10, 15) or(no problem also)
removeElements(a, 4) ==> remove four elements at indexes (3,7,11 , 15) or ( 3 ,7,11,14) for example ..
what I want is if I draw the values in the source array on (chart on Excel for example) and I draw the values from the new array , I must get the same line (or close to it).
I think the main problem in your code is that you are binding the selection to
(inputArr.length ) / numberOfElementToDelete
This way you are not considering the first and the last elements that you don't want to remove.
An example:
if you have an array of 16 elements and you want to delete 6 elements it means that the final array will have 10 elements but, since the first and the last are fixed, you'll have to select 8 elements out of the remaining 14. This means you'll have to select 8/14 (0,57) elements from the array (not considering the first and the last).
This means that you can initialize a counter to zero, scan the array starting from the second and sum the value of the fraction to the counter, when the value of the counter reach a new integer number (ex. at the third element the counter will reach 1,14) you'll have an element to pick and put to the new array.
So, you can do something like this (pseudocode):
int newLength = originalLength - toDelete;
int toChoose = newLength - 2;
double fraction = toChoose / (originalLength -2)
double counter = 0;
int threshold = 1;
int newArrayIndex = 1;
for(int i = 1; i < originalLength-1; i++){
**counter += fraction;**
if(integerValueOf(counter) == threshold){
newArray[newArrayIndex] = originalArray[i];
threshold++;
**newArrayIndex++;**
}
}
newArray[0] = originalArray[0];
newArray[newArray.length-1] = originalArray[originalArray.length-1];
You should check for the particular cases like originalArray of length 1 or removal of all the elements but I think it should work.
EDIT
Here is a Java implementation (written on the fly so I didn't check for nulls etc.)
public class Test {
public static void main(String[] args){
int[] testArray = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int[] newArray = remove(testArray, 6);
for(int i = 0; i < newArray.length; i++){
System.out.print(newArray[i]+" ");
}
}
public static int[] remove(int[] originalArray, int toDelete){
if(toDelete == originalArray.length){
//avoid the removal of all the elements, save at least first and last
toDelete = originalArray.length-2;
}
int originalLength = originalArray.length;
int newLength = originalLength - toDelete;
int toChoose = newLength - 2;
int[] newArray = new int[newLength];
double fraction = ((double)toChoose) / ((double)originalLength -2);
double counter = 0;
int threshold = 1;
int newArrayIndex = 1;
for(int i = 1; i < originalLength-1; i++){
counter += fraction;
if(((int)counter) == threshold ||
//condition added to cope with x.99999999999999999... cases
(i == originalLength-2 && newArrayIndex == newLength-2)){
newArray[newArrayIndex] = originalArray[i];
threshold++;
newArrayIndex++;
}
}
newArray[0] = originalArray[0];
newArray[newArray.length-1] = originalArray[originalArray.length-1];
return newArray;
}
}
Why cant you just initialize i=0
for (int i = 0; i < inputArr.length; i++) {
if ((i + 1) % f != 0) {
Following is the output:
arr[0]=1.0
arr[1]=1.0
arr[2]=3.0
arr[3]=5.0
arr[4]=7.0
arr[5]=9.0
arr[6]=11.0
arr[7]=13.0
arr[8]=15.0
arr[9]=16.0
This is Reservoir sampling if I understand it right i.e from a large array, create a small array by randomly choosing.

Trying to port python code to Java but getting different results

I'm sure I'm making a rookie mistake with java(this is actually my first program). I am trying to port some working python code I made into java(as a learning/testing exercise to learn a bit of the differences) but I'm getting different results between the two.
My program takes a list of data and generates another list based on it(basically sees if a value can be broken down by a sum). Python correctly gives 2,578 results while Java only gives 12. I tried to find the same commands in java and thought I did but can't seem to figure out why the results differ(the difference between the two I have experienced problems with multi threading and syncing of variables, wasn't sure if Java was doing anything behind the scenes so I had a while loop to keep running until the results stabilize, but it didn't help). Any suggestions would be helpful.
Here's the offending code(java at the top, python and pseudo code commented out in the bottom as reference):
for (int c = 0; c <= max_value; c++){
String temp_result = (s - c * data.get(i) + "," + i);
if( results.contains( temp_result ) ){
String result_to_add = (s + "," + i+1);
if( results.contains( result_to_add ) ){
System.out.println("contains result already");
} else {
results.add(result_to_add);
} print len(T)
#Here's the basic pseudo code(I added a few control variables but here's a high level view):
for i = 1 to k
for z = 0 to sum:
for c = 1 to z / x_i:
if T[z - c * x_i][i - 1] is true:
set T[z][i] to true
*/
In java s + "," + i+1 is a String concatenation : "10" + "," + 4 + 1 will return 10,41.
Use String result_to_add = s + "," + (i+1); instead.
I see you've solved it just now, but since I've written it already, here's my version:
This uses the trick of using a Point as a substitute for a 2-element Python list/tuple of int, which (coincidentally) bypasses your String concatenation issue.
public class Sums
{
public static void main(String[] args)
{
List T = new ArrayList();
T.add(new Point(0, 0));
int target_sum = 100;
int[] data = new int[] { 10, -2, 5, 50, 20, 25, 40 };
float max_percent = 1;
int R = (int) (target_sum * max_percent * data.length);
for (int i = 0; i < data.length; i++)
{
for (int s = -R; s < R + 1; s++)
{
int max_value = (int) Math.abs((target_sum * max_percent)
/ data[i]);
for (int c = 0; c < max_value + 1; c++)
{
if (T.contains(new Point(s - c * data[i], i)))
{
Point p = new Point(s, i + 1);
if (!T.contains(p))
{
T.add(p);
}
}
}
}
}
System.out.println(T.size());
}
}

Categories

Resources