Separate stream of numbers into groups of closer integers - algorithm

I have a stream of numbers such as
[2872, 2997, 3121, 13055, 14178, 14302, 23134, 23382, 23507, 32832, 33677, 34017, 43415, 44246, 44374, 52866, 54035, 54158, 62835, 64243, 64936, 73110, 73890, 74014, 82809, 83771, 83899, 93436, 94765, 94891].
I would like to split it as follows:
[[2872, 2997, 3121], [13055, 14178, 14302], [23134, 23382, 23507], [32832, 33677, 34017], [43415, 44246, 44374], [52866, 54035, 54158], [62835, 64243, 64936], [73110, 73890, 74014], [82809, 83771, 83899], [93436, 94765, 94891]].
It is to be noted that the distance between the groups could be closer to each other, also the digits within a group could be farther away.

This is not an answer, but a way to look at your data, which should be insightful.
Original values:
Deltas:

Can't you just create a list of list of integers (or array of array) with size N/3 (N being the total of your numbers), and then just loop on this length and put the minimal number in it?
Something like this (I don't know what language you are using so I use c# as exemple):
int len = numbersStream.count();
List<List<int>> BigList = new List<List<int>>();
List<int> smallList = new List<int>();
for (int i = 0; i < len; ++i)
{
smallList = new List<int>();
for (int j = 0; j < 3; ++i)
{
int value = Math.Min(numbersStream);
smallList.Add(value);
numbersStream.remove(value);
}
BigList.Add(smallList);
}
BigList will be : (2872, 2997, 3121), (13055, 14178, 14302) etc...
*Assuming you always have exactly %3 numbers, otherwise you just tune the algorithm to avoid exceptions

The solution is in java but basically what this does is find the average delta and groups everything in a subset if the difference between the two elements is smaller then that average. You can fine tune this process by changing how the averageDelta operates
ps. this solution assumes your input is at least 1 large and called temp
int[] diffrence = new int[temp.length-1];
for (int i=1; i < temp.length; i++) {
diffrence[i-1] = temp[i]-temp[i-1];
}
int averageDelta = (int) Math.round(Arrays.stream(diffrence).average().orElse(1.0));
List<List<Integer>> resultList = new ArrayList<>();
List<Integer> currentList = new ArrayList<>();
currentList.add(temp[0]);
for (int i=1; i < temp.length; i++) {
if (temp[i]-temp[i-1] > averageDelta) {
resultList.add(currentList);
currentList = new ArrayList<>();
}
currentList.add(temp[i]);
}
resultList.add(currentList);
System.out.println(resultList.toString());

Related

Looping through an arraylist of object variables and inputing them into an array in Processing

This is a section of my code, I have an ArrayList of 10 objects called "bob" and I want to loop through them so that each of their names (a local integer defined in the bob class) to be put in the array named "names" in order.
for (bob b : bob) {
for (int i = 0; i < 10; i++){
names[i] = b.name;
}
}
I tried this approach:
for (bob b : bob) {
for (int i = 0; i < 10; i++){
names[i] = b[i].name; //I added the "[i]" after b attempting to loop through
//the arraylist but it does not work
}
}
the syntax does not seem to allow me to loop through the arraylist of the objects like that. I am a beginning programmer so please excuse my lack of programming knowledge. It would be very helpful if someone could at least give me an idea of where to go from here. Thank you in advance!
When dealing with ArrayList you need to use the set() and get() methods to access the contents of it. Here's a somewhat hamfisted attempt at recreating the scenario you describe. Hope it helps.
class Bob {
int name;
Bob() {
this.name = floor(random(10000));
}
}
void setup(){
ArrayList<Bob> alb = new ArrayList<Bob>();
for(int i = 0; i < 50; i++){ //populate ArrayList
alb.add(new Bob());
}
int[] names = new int[10];
for(int i = 0; i < names.length; i++){
names[i] = alb.get(i).name; // use get() method
}
for(int i = 0; i < names.length; i++){
print(names[i]);
print('\n');
}
}
Your question highlights two techniques for iterating over a collection: with or without, an index. Each is best suited for different data structures and scenarios. It takes some experience to decide when to use one or the other, and is also a matter of personal style.
It is common to write code like for( int x: myInts ) and then realize you want the index of the current item, which isn't available. Or conversely, to write code like for( int i=first; i<last; i++) and then become irritated because determining first and last is tedious, or prone to bugs.
Notice your code is a double-nested loop. It says "iterate over each item in the collection Bob, and then for each one, iterate over each item in the collection of names". So if Bob had ten items, this would iterate one hundred total times, probably not what you want. You need to rewrite as a single, non-nested for loop ...
If you decide to iterate without an index, then names should be some type of list, where you can add items using append(). Consider the StringList available in Processing. Otherwise if you decide to iterate with an index, then names could be an array, although it could still be a list if it was already populated with old values which you wish to overwrite. The following shows both techniques:
void setup()
{
ArrayList<String> baseList = new ArrayList<String>(10);
for( int i=0; i<10; i++ )
baseList.add( i, Integer.toString( i + (i*10) ) );
// Approach 1: Iterate without an index,
// build a list with no initial allocation and using append()
StringList namesList = new StringList();
for( String s : baseList )
{
namesList.append( s );
println( namesList.get( namesList.size()-1 ) );
}
// Approach 2: Iterate with an index,
// build a list using preallocation and array access
String[] namesArray = new String[10];
for( int i=0; i<10; i++ )
{
namesArray[i] = baseList.get(i);
println( namesArray[i] );
}
}

Simple Sort function not working. Suggestions?

void sort_records_by_id (int []indices, int []students_id )
{
for (int k = 1; k<students_id.length; k++)
{
for (int j = k; j>0 && students_id[j]<students_id[j-1]; j--)
{
int place_holder = indices[j];
indices[j] = indices [j-1];
indices[j-1] = place_holder;
}
}
}
Hi,
I have to create a function that is able to sort an array of integers, not by changing and rearranging its contents, but by changing the order of integers in another array of integers called indexes. So, I would have an array with a series of ids such as: Lets call this id" [#] represents index [0]10001 12001 212334 [3]14332 [4]999999 [5]10111
There is a corresponding array, with integer values [#] is the index Lets call this arr [0]0 11 [2}2 [3]3 [4]4 [5]5 So that they correspond to the indexes we have in the other array.
Now, we must change the order of "arr", such that the elements are in such an order that it corresponds to the order of indexes in array id in sorted order. Note, array id is not changed in any way.
So, we can print the ids to the console in ascending order, by using a for loop, the values of arr, and array id.
Please, I would really appreciate if you would be able to provide advice without creating a very complex function. I would just like to alter my existing function I created so that it works.
This is the output of my function so far:
Any input or suggestions would be greatly appreciated.
When indexing students_id array, don't use j and j-1, but instead of this -> indices[j] and indices[j-1]. Thanks to that, you will change order in indices array using students_id array to get values to comparison.
for (int j = k; j>0 && students_id[indices[j]]<students_id[indices[j-1]]; j--)
Also I would change loop into
void sort_records_by_id (int []indices, int []students_id )
{
for (int k = 1; k<students_id.length; ++k)
{
for (int j = 0; j<k; ++j)
{
if(students_id[indices[j]]>students_id[indices[j+1]]) {
int place_holder = indices[j];
indices[j] = indices [j+1];
indices[j+1] = place_holder;
}
}
}
}
The simplest bubble sort - that's what comes to my mind.

Nested For Loops Explanation Needed

Basically, in this program, I was instructed to create an array of random numbers and then sort them smallest to largest by bubble sorting with for loops. With a bunch of trial and error, my buddy and I were able to figure it out but I just took a look back at my code and honestly, it's very hard to comprehend.. I'm not too familiar with nested loops so if someone could explain how this method is working, that would be awesome. More specifically, what does the value j and i stand for.
public void sort() {
int val = 0;
for(int i = 0; i < myArray.length; i++) {
for(int j = 1; j < (myArray.length - i); j++) {
if(myArray[j-1] > myArray[j]) {
val = myArray[j-1];
myArray[j-1] = myArray[j];
myArray[j] = val;
}
}
}
}
Any answers are greatly appreciated, thanks guys/gals!
i and j are short with no inherent meaning other than to represent the index you are at in the array. The first for loop is so that the second loop and the sorting method are repeated for as many items are in the array. The second loop does the sorting.
if(myArray[j-1] > myArray[j]) { // Checks if the index `j` in the array is less than the one before it.
val = myArray[j-1]; // Temporarily stores the greater value.
myArray[j-1] = myArray[j]; // Swap the numbers.
myArray[j] = val; // Swap the numbers.
}

Sorting integers

I'm something of a beginner to the art and science of algorithms,and as I was learning about "Quick Sort" (which is allegedly quite fast) I had an idea for a sort that uses a dictionary. I coded it up, and I was quite surprised that for what I was interested in (sorting, say, earth temperatures or elevation data) that what I had coded up was actually faster than C# .NET's List.Sort() once I compiled it in Release mode. For example, if I create a list of one million integers loaded with values ranging from zero to 8000 (a good range for typical Earth elevations), the .NET List.Sort() method averages about 88 milliseconds to sort the list, while the algo below does so in about 58 milliseconds.
So this gets me thinking that I should either be up for the Nobel prize for computer science (unlikely) or that there is something that I am missing and that there is a much more efficient way of sorting a large number of integers in the range say of zero to 10,000. How would you experts sort a large amount of data in that range?
private static long DictionarySort(List<int> myList, out List<int> sortedList)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int max = myList.Max();
Dictionary<int, int> sorter = new Dictionary<int, int>();
int myListCount = myList.Count;
for (int i = 0; i < myListCount; i++)
{
int val = myList[i];
int occurances = 0;
sorter[val] = sorter.TryGetValue(val, out occurances) ? occurances + 1 : 1;
}
sortedList = new List<int>(myList.Count + 1);
int numOccur = 0;
for (int i = 0; i <= max; i++)
{
if (sorter.TryGetValue(i, out numOccur))
{
for (int j = 0; j < numOccur; j++)
{
sortedList.Add(i);
}
}
}
sw.Stop();
return sw.ElapsedMilliseconds;
}
You've rediscovered what Wikipedia calls counting sort, a very simple distribution sorting algorithm. It is the optimal algorithm for your data set: it runs in O(N + k) time (N is number of records and k is number of distinct keys), uses O(k) additional storage, and has very low coefficients.

How to generate random numbers with out repetition in windows phone app

here is the code for generating random numbers,but I am getting duplicate numbers,how can I overcome this.
void getnumbers()
{
Random r = new Random();
int[] trubyte = new int[4];
for (var x = 0; x < 4; ++x)
{
trubyte[x] = r.Next(1, 5);
}
b1.Content = trubyte[0];
b2.Content = trubyte[1];
b3.Content = trubyte[2];
b4.Content = trubyte[3];
}
Just get another random number if the method returns one that you already have.
void getnumbers()
{
Random r = new Random();
int num;
var trubyte = new List<int>();
for (var x = 0; x < 4; ++x)
{
do
{
num = r.Next(1, 5);
} while(trubyte.Contains(num));
trubyte[x] = num;
}
b1.Content = trubyte[0];
b2.Content = trubyte[1];
b3.Content = trubyte[2];
b4.Content = trubyte[3];
}
I'm using List instead of an array just because it offers the Contains method right away, not any other special reason.
This is not efficient if you want to generate a big list of random, unrepeated numbers (it's O(n^2) in the worst case) but for 4 numbers it's more than enough ;)
A random number generator function can return duplicates, because the output is random.
If you are using an RNG to generate numbers which must be unique, you will need to verify that they have not already been generated before using them.
Can't you use something like this [0] on Windows Mobile? It seems more practical than writing your own RNG.
0: http://msdn.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator(v=vs.90).aspx
You have to do it by yourself, that means checking if a number was already generated.
You can do it like gjulianm said, but it is a long list of numbers, say 1000 you would be wasting a lot of time. So if you want a randomized list of 1000 you could proceed the following way
Initialize an array trubyte of size 1000 with trubyte[0]=1,trubyte[1]=2 and so on...
Initialize a variable arraysize=1000
run a loop 1000 times in which first extract a random number k btw 0-(arraysize-1). Your random number is a[k] which you can separately in a list. Now swap trubyte[k] with trubyte[arraysize]. And finally decrease the arraysize by one.
Another way, if you don't want the numbers while in the loop is just to use the changed list after the execution of loop
void getnumbers(){
Random r = new Random();
int num;
int[] trubyte = new int[1000];
int finalList[] = new int[1000]
for (int x = 0; x < 1000; ++x)
{
trubyte[x]=x+1;
}
int arraysize=1000;
for (var x = 0; x < 1000; ++x)
{
int k=r.Next(0, arraysize);
finalList[x]=trubyte[k];
trubyte[k]=trubyte[arraysize-1];
arraysize--;
}
//use the finalList
}
we can use dictionary instead of hash-set in windows phone application.
below is the code for generating distinct random numbers.
static int[] GetRandomNumbersNonrepeat(int noOfRandomNumbers, int maxValue)
{
Dictionary<int, int> randomnumbers = new Dictionary<int, int>();
while (randomnumbers.Count < maxValue)
{
Random r = new Random();
int rnum = r.Next(1, maxValue+1);
if (!randomnumbers.ContainsValue(rnum))
{
randomnumbers.Add(randomnumbers.Count + 1, rnum);
}
}
int[] rnums = randomnumbers.Values.ToArray<int>();
return rnums;
}

Resources