Sort array with goal to minimize sequence repeat - arrays

Ok so I have an array of websocket client connections. Imagine that this array contains connections to several different machines. Imagine that each different letter (1,2,3, etc) represents a different host. It might look like this:
const conns = [1,1,1,3,3,1,3,2,2,2,2,3,2,1,1,2,2];
what I would like to do, is sort the array like so:
const conns = [1,2,3,1,2,3,1,2,3, ... etc];
the rationale is if a client does not respond, I don't want to retry to the same host, I would like to try sending a message to a client on a different host, and only come back to the original host later. This is basically like a round-robin type thing.
I assume the best way to sort the array like this is:
find all the different hosts (unique letters) in the array
Iterate over this unique list, and splice off items from the original array as I go.
Here is the JS code I have for the above algorithm:
const list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
const _ = require('lodash');
function findAndRemoveFirstMatch(m, list){
for(var i = 0; i < list.length; i++){
if(m === list[i]){
return list.splice(i,1)[0];
}
}
}
function getSorted(list){
const ret = [];
const set = _.uniqBy(list, function(x){
return x;
});
while(list.length > 0){
var i = 0;
while(i < set.length && list.length > 0){
var item;
if(item = findAndRemoveFirstMatch(set[i],list)){
ret.push(item);
}
i++;
}
}
return ret;
}
console.log(getSorted(list));
//given the above input, we get:
[ 1, 2, 3, 4, 5, 11, 1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 3, 4, 1, 3, 4, 1, 3, 1, 3, 1, 1, 1 ]
I am not proud of this code, and am wondering if there is a better way to do it. The above works for this input, but looking for a good way to clean it up and make it more generic.
Is there a better/faster way to do this?

You can do it differently:
sort input - it will help later
find maximum count of equal elements (10 in your example, for element=1), cnt
create cnt buckets to distribute elements over them
put elements in sorted order one by one into next bucket with round-robin principle
merge buckets
This way you get longer series in the end, 1 less than at the beginning.
[1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 3, 4, 1, 3, 4, 1, 3, 5, 1, 3, 5, 1, 3, 11, 1, 3, 1, 3]
Bad case is when one element appears more than n/2 times, but that's unavoidable.
var list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
var a = list.sort(function(a, b) { return a - b; });
var cnt = a.reduce(function(res, cur) {
if (cur == res[0])
return [cur, res[1]+1, Math.max(res[1]+1, res[2])]
else
return [cur, 1, Math.max(1, res[2])];
}, [null, 0, 0])[2];
var buckets = [];
for (var i = 0; i < cnt; i++)
buckets[i] = [];
var j = 0;
for (var i = 0; i < a.length; i++) {
buckets[j].push(a[i]);
j = (j+1)%cnt;
}
var res = buckets.reduce(function(r, cur) {
return r.concat(cur);
});
If you insist on full list of key from beginning, it's also possible:
var list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
var a = list.sort(function(a, b) { return a - b; });
var cnt = a.reduce(function(res, cur) {
if (cur == res[0])
return [cur, res[1]+1, Math.max(res[1]+1, res[2])]
else
return [cur, 1, Math.max(1, res[2])];
}, [null, 0, 0])[2];
var buckets = [];
for (var i = 0; i < cnt; i++)
buckets[i] = [];
var j = 0;
var cur = null;
for (var i = 0; i < a.length; i++) {
if (cur != a[i])
j = 0;
buckets[j].push(a[i]);
j = j+1;
}
var res = buckets.reduce(function(r, cur) {
return r.concat(cur);
});

Related

Given an index, swap array elements accordingly

What I am trying to achieve is somewhat like a radio group behavior, where only one radio input can be selected at a time. For example, the starting array [0, 1, 1, 1, 1, 1] should have its elements swapped in the following way:
index
array
0
[0, 1, 1, 1, 1, 1]
1
[1, 0, 1, 1, 1, 1]
2
[1, 1, 0, 1, 1, 1]
3
[1, 1, 1, 0, 1, 1]
4
[1, 1, 1, 1, 0, 1]
5
[1, 1, 1, 1, 1, 0]
I have come up with this, but I think it does "extra work" (unnecessary loops) in certain scenarios.
function rearrange(array: number[], idx: number) {
let arr = array.slice();
let l = arr.length;
if (arr.indexOf(0) === idx) return arr;
while (arr.indexOf(0) !== idx) {
let swap;
for (let i = 0; i < l; i++) {
if (arr[i] === 0 || arr[i + 1] === 0) {
swap = arr[i];
if (i + 1 < l) {
arr[i] = arr[i + 1];
arr[i + 1] = swap;
}
if (i + 1 > l) {
arr[i] = arr[i - 1];
arr[i - 1] = swap;
}
}
}
}
return arr;
}
I was wondering if you would have ideas on how to make this process simpler/better.
Just identify the previous 0 with findIndex, assign 1 to it, and assign 0 to the idx?
function rearrange(array: number[], idx: number) {
const arr = [...array];
arr[arr.indexOf(0)] = 1;
arr[idx] = 0;
return arr;
}
Another approach...
const rearrange = (array: number[], idx: number) => (
array.map((_, i) => i === idx ? 0 : 1)
);
Instead of swapping pairs, you can rotate the subarray in "one go", using slice and splice.
Here is a function that does the job, mutating the given array (not returning a new one), together with a sequence of calls to demonstrate it. I assume values could be varying and need to stay together as if they were swapped with the "moving" 0:
function rearrange(array, idx) {
let zero = array.indexOf(0);
if (zero < idx) {
arr.splice(zero, idx - zero + 1, ...arr.slice(zero + 1, idx + 1), 0);
} else {
arr.splice(idx, zero - idx + 1, 0, ...arr.slice(idx, zero));
}
}
arr = [0,1,2,3,4,5];
rearrange(arr, 3);
console.log(...arr);
rearrange(arr, 1);
console.log(...arr);
rearrange(arr, 5);
console.log(...arr);
rearrange(arr, 1);
console.log(...arr);

Creating a 2d array in flutter / dart

I'm brand new to flutter and dart. I've searched google and all I can find is how to make 1d lists in flutter. I need a chart of values.
Specifically I need a row 12 long and a column 31 long filled with ascending numbers
1, 32, 63,
2, 33, 64,
3, 34, 65, etc....
thanks!
int row = 3;
int col = 4;
var twoDList = List.generate(row, (i) => List(col), growable: false);
//For fill;
twoDList[0][1] = "deneme";
print(twoDList);
// [[null, deneme, null, null], [null, null, null, null], [null, null, null, null]]
Your 2D list having 3 rows and 4 columns.
Declare and initialize a matrix x having m rows and n columns, containing real numbers.
var x = new List.generate(m, (_) => new List(n));
You can use smart_arrays_numerics package...
look at this..
https://pub.dev/packages/smart_arrays_numerics
else you should use nested list.
List<List<int>>
and create your list with generator
To get exactly what you want, you could use double List.generate, i.e.:
const cols = 31;
const rows = 12;
final array = List.generate(rows,
(i) => List.generate(cols + 1, (j) => i + j * cols + 1, growable: false),
growable: false);
array.forEach((row) {
print(row);
});
// [1, 32, 63, ...
// [2, 33, 64, ...
// [3, 34, 65, ...
// ...
There is also List.filled, where you can fill the array with some initial value when created. The following init the 2d array with 0s.
final array = List.generate(rows + 1, (i) => List.filled(cols + 1, 0, growable: false), growable: false);
To declare and initialize the array 2D in the dart, you can use:
List<List<int>> a =
[
[10, 2, 4, 6, -2],
[ 1, -16, 6, -2, -5],
[ 0, 3, 10, -5, 1],
[ 0, -4, 1, 18, 2],
[ 3, 1, 2, 2, -14],
];
#vahab
so would I do
final int NROWS = 12, NCOLS = 31;
List<Float64List> matrix = List(NROWS);
for (int i = 0; i < 373; i++) {
Float64List row = Float64List(NCOLS);
for (int k = 0; k < NCOLS; k++) { //I dont know what this does
row[k] = double.parse("$i.$k");
}
matrix[i] = row;
}
I would use a nested collection-for:
const maxRows = 31;
const maxColumns = 12;
var matrix = [
for (var row = 0; row < maxRows; row += 1)
[for (var column = 0; column < maxColumns; column += 1)
1 + row + column * maxRows],
];
Just use this statement i got this same problem, Got resolved
var list1 = List.generate(12,(i) => List.generate(31, (j) =>{Your equation to genearte })));
To initialize a 2d matrix filled with 0 :
List.generate(numberRows, (_) => List.filled(numberColumns, 0));

Find and return the element which occurs most frequently in an array

I need to implement a function called findMode to find the mode of an array. Assuming the array contains integer numbers only. When the function is called and the array is empty it returns 0. When the function is called and the array isn't empty it should return the element which occurs most frequently in an array. If an array contains multiple modes it should return the smallest value of the modes. I need to create an intermediate array, another array of numbers to count the number of times each value occurs. This array should use the index numbers of the array to track of how many times a number in b has been counted.
below is what I have so far:
import { print } from "....";
export let main = async () => {
let input = [2, 1, 1, 2, 1, 0]
print(mode(input))
};
export let findMode = (b: number[]): number => {
let newArr: number[] = []; /** this is the new number array created to store count, this is the intermediate array */
if (b.length === 0) {
return 0;
for (let i = 0; i < b.length; i++) {
};
main();
Here are the expected/actual results:
If the array is b[2,1,1,2,1,0] then 1 should be returned, and if we printed the array we created to store the count it should print newArr[1,3,2] because element 0 has 1 occurrence, element 1 has 3 occurrences, and element 2 has 2 occurrences. The idea is to go from 0 as an element in our input array to it 0 being an index in our intermediate array. so lastly we see which is our max occurrences ( or max element in our intermediate array) which is 3 at index 1, so the mode is 1.
If the array is b[0,0,0,1,1,2,1,1] then 1 should be returned. If the array is b[4,4,7,4,0,7] then 4 should be returned. If the array is b[-4,-4,-1,3,5] then -4 should be returned. If the array is b[1,1,2,3,2] then 1 should be returned since its the smallest of the modes. If the array is b[10,10,10,20,20,30] then 10 should be returned.
Would something like this work?
export let findMode = (b: number[]): number => {
// we'll store the values in b and the number of times they occur here
const counts: Array<{ value: number, count: number }> = [];
// it helps to check that b is defined before you check length, this avoids ReferenceErrors
if (!b || !b.length) {
return 0;
}
for (let i = 0; i < b.length; i++) {
const val = b[i];
const count = counts.find(count => count.value === val);
if (count) {
count.count++;
} else {
counts.push({ value: val, count: 1 });
}
}
// get the mode by sorting counts descending and grabbing the most occuring
const mode = counts.sort((c1, c2) => c2.count - c1.count)[0];
// and now if you *need* an intermediate array with the index mapped to the value and value mapped to the count:
const largestNumber = counts.sort((c1, c2) => c2.value - c1.value)[0];
// initialize an empty as long as the largest number
let newArr = new Array(largestNumber);
newArr = newArr.map((val, i) => {
const count = counts.find(count => count.value === i);
if (count) {
return count.count;
} else {
return 0; // 'i' occurs 0 times in 'b'
}
});
};
You can use Array#reduce method to achieve the result with an additional object for keeping count.
export let findMode = (b: number[]): number => {
// object for keeping count of each element
// initially set `0` with 0 count (default value)
let ref = {
'0': 0
};
return b.reduce((value, num) => {
// define count as 0 if not defined
ref[num] = ref[num] || 0;
// increment element count
ref[num]++;
// if number count is gretater than previous element count
// then return current element
if (ref[num] > ref[value]) {
return num;
// if counts are same then return the smallest value
} else if (ref[num] === ref[value]) {
return num < value ? num : value;
}
// else return the previous value
return value;
// set initial value as 0(default)
}, 0);
};
let findMode = b => {
let ref = {
'0': 0
};
return b.reduce((value, num) => {
ref[num] = ref[num] || 0;
ref[num]++;
if (ref[num] > ref[value]) {
return num;
} else if (ref[num] === ref[value]) {
return num < value ? num : value;
}
return value;
}, 0);
};
[
[2, 1, 1, 2, 1, 0],
[1, 3, 2],
[0, 0, 0, 1, 1, 2, 1, 1],
[4, 4, 7, 4, 0, 7],
[-4, -4, -1, 3, 5],
[1, 1, 2, 3, 2],
[10, 10, 10, 20, 20, 30]
].forEach(v => console.log(findMode(v)))

Looping through Array, return largest number

For the Life of me i can not understand why this doesn't work.
I'm trying to find the Largest number in the array. Plz explain what I did wrong here.
function largestOfFour(arr) {
var maxArry = [];
for (let i = 0; i < arr.length; i++) {
var Max = 0;
for (let y = 0; y < arr.length; y++) {
var currentElement = arr[i][y];
if (currentElement >= Max) {
Max = currentElement;
}
}
console.log(Max);
}
}
largestOfFour([
[4, 5, 6, 7, 9],
[9, 4, 5, 64, 3],
[4, 4, 6, 8, 35],
[3, 5, 76, 54, 3]
]);
Try this:
function largestOfFour(arr) {
var largestNr = 0;
arr.map(child => {
var largestChild = Math.max(...child)
if (largestChild > largestNr) largestNr = largestChild
})
return largestNr;
}
or if you care about IE browser support of Spread opearator, use:
var largestChild = Math.max.apply(null, child)
Array.Map() is more reliable these days because it's easier to use and less bug-prone :)
You can read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Try this for sort array:
var Arr = [1, 7, 2, 8, 3, 4, 5, 0, 9];
for (var i = 1; i < Arr.length; i++)
for (var j = 0; j < i; j++)
if (Arr[i] > Arr[j]) {
var x = Arr[i];
Arr[i] = Arr[j];
Arr[j] = x;
}
console.log(Arr);
then get four first item in array.
Your variable assignment of Max needs to go outside your for loop as every time you finish your inner loop, Max will reset to 0 as you iterate through the outer loop.

How to find the lowest number in an array? [duplicate]

This question already has answers here:
Find min / max value in Swift Array
(16 answers)
Closed 1 year ago.
I am writing an algorithm to find the lowest number in an array however my print statement keeps saying that the lowest number is 0. I have the following:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValue = numbers[0]
var isSmallest: Bool
for i in 0...numbers.count {
isSmallest = true
for j in 0...numbers.count {
if i > j {
isSmallest = false
}
}
if isSmallest {
minValue = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
My print statement returns as:
"Smallest value in the list is 0\n"
I feel like the algorithm is correct. Any ideas?
EDIT: Answered my own question
I was iterating over indices and not actual values. Thanks to one of the users in the comments. The correct code should be:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValue = numbers[0]
var isSmallest: Bool
for i in list {
isSmallest = true
for j in list {
if i > j {
isSmallest = false
}
}
if isSmallest {
minValue = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
Simply
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minValue = list.min()
For logic use try this
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
var minValue = list[0]
for num in list {
minValue = (num < minValue) ? num : minValue
}
print("Smallest value in the list is \(minValue)")
For direct get min value by property
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minValue = list.min()
Or you could just use
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
list.min() // returns 2
If you'd like to find the min value without an extra loop, try this:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValIdx = 0
var minValue = numbers[0] as! Int
for i in 1..<numbers.count {
if (numbers[i] as! Int) < minValue {
minValue = numbers[i] as! Int
minValIdx = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
You can use this code in Swift for manual algorithm:
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
var smallest = list[0]
for item in list {
if (item < smallest) {
smallest = item
}
}
print("smallest number is: \(smallest)")
And if you want Swift to do the hard work then use this:
let smallest = list.min()
print("smallest number is: \(smallest)")
here it is your solution
let numbers = [1, 6, 3, 9, 4, 6]
let min = minElement(numbers) // 1
let position = find(array, min)// it will return index
Just to throw a few more options out there, assuming you have to actually show some logic:
func min<T:Comparable>(_ elements:[T]) -> T? {
guard let first = elements[0] else {
return nil
}
return elements.reduce(first, min)
}
print(min(list))
or put it in an extension, this is essentially the definition of Array.min
extension Array where Element : Comparable {
func smallest() -> Element? {
guard let first = self.first else {
return nil
}
// Use 'Swift.min' to get to the global function since Array
// already has a min function
return reduce(first, Swift.min)
}
}
print(list.smallest())
You can use this code:
it is in C#
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
int minVal = list[0];
for (int i = 1; i < list.Length; i++)
{
if (list[i] < minVal)
{
minVal = intArray[i];
}
}
To find the minimum element in the sequence, Swift 3 have an istance method called min():
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minElem = list.min()
If the sequence has no elements, returns nil.
This method can be used also for a list of floats:
let heights = [67.5, 65.7, 64.3, 61.1, 58.5, 60.3, 64.9]
let minHeight = heights.min()
You can find the official document referece here

Resources