Related
Following approaches works on small number of arrays but when I try large volume then it is timing out. What is the best way to check all numbers are equal in large volume of arrays?
In below sample, I am confirming which numbers are uniform between given numbers where it works for small volume (i.e., 1 - 300) but not doing well for large volume (i.e., 1 - 999999999999)
References:
Check if all values of array are equal
Check if each item in an array is identical in JavaScript
using .every
const uniformInteger = (A, B) => {
let output = 0;
for (let i = A; i <= B; i++) {
const reversed = i.toString().split("").reverse();
// Option - 1 = using .every
if (reversed.every((val, i, arr) => val === arr[0])) {
output++;
}
}
return output;
};
console.log(uniformInteger(1, 300));
// Timed out
// console.log(uniformInteger(1, 999999999999));
using Set
const uniformInteger = (A, B) => {
let output = 0;
for (let i = A; i <= B; i++) {
const reversed = i.toString().split("").reverse();
// Option - 2 = using Set
if (new Set(reversed).size == 1) {
output++;
}
}
return output;
};
console.log(uniformInteger(1, 300));
using another loop to check current and next value
function identical(array) {
for (var i = 0; i < array.length - 1; i++) {
if (array[i] !== array[i + 1]) {
return false;
}
}
return true;
}
const uniformInteger = (A, B) => {
let output = 0;
for (let i = A; i <= B; i++) {
const reversed = i.toString().split("").reverse();
// Option - 3 = another loop to check current and next value
if (identical(reversed)) {
output++;
}
}
return output;
};
console.log(uniformInteger(1, 300));
If it's just about counting how many numbers in a certain range have all equal digits, there is no need to inspect billions of numbers which never can fulfill the condition. Optimizing is often not about making the existing approach faster but to check whether there is a better approach for calculating the result.
Because for instance, if you have reached 111111111111 the next number to fulfill your condition will be 222222222222. No need for checking 111111111112, 111111111113, 111111111114 ...
But you can easily calculate the count, because for each "length" of a number (ie 1s, 10s, 100s, 1000s, ....) there are exactly 9 numbers which meet your condition (ie 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 111, 222, 333 ...)
Thus for an interval [1, B] where B = 99999.... the count of numbers fulfilling your condition is
ceil(log_10(B)) * 9
Ie for instance, if B == 999 it would be
ceil(log_10(999)) * 9 = ceil(2.99...) * 9 = 3 * 9 = 27
//(ie 1, 2, 3, ..., 9, 11, 22, 33, ..., 99, 111, 222, 333, ..., 999)
If B does not consist of all 9 you have to check if any digit of B is less than the first digit of B or not.
If yes, then the count is
floor(log_10(B)) * 9 + firstDigit - 1
If no, then the count is
floor(log_10(B)) * 9 + firstDigit
Actually, the B = 999.... case can also be handled with these two formulae.
So for instance, if B == 323 the count is
floor(log_10(B)) * 9 + firstDigit - 1 = 2 * 9 + 3 - 1 = 20
//(ie, 1, 2, 3, ..., 9, 11, 22, 33, ..., 99, 111, 222)
If B === 343 then count is
floor(log_10(B)) * 9 + firstDigit = 2 * 9 + 3 = 21
//(ie, 1, 2, 3, ..., 9, 11, 22, 33, ..., 99, 111, 222, 333)
EDIT
If you have an interval [A,B] where A != 1 the final result is of course
count(A,B) = count(1,B) - count(1,A - 1)
I'm not gonna comment on your linked fiddles, because they contain so many errors, I don't even know where to start. So I'm just adding a simple and straight forward implementation
function count(a, b) {
if (a > b || a < 1 || b < 1)
return 0;
if (a > 1)
return count(1, b) - count(1, a - 1);
let
result = 9 * Math.floor(Math.log10(b)),
smallest = 9,
first = 0
while (b > 0) {
smallest = Math.min(smallest, b % 10)
first = b;
b = Math.floor(b / 10)
}
result += first;
if (smallest < first) result -= 1;
return result;
}
let testinvervals = [
[1,1],
[1, 10],
[1, 1000],
[1, 1234],
[1, 4321],
[2, 9],
[2, 10],
[2, 11],
[11, 99],
[12, 99],
[11, 22],
[33, 33]
]
for (let tv of testinvervals) {
console.log(`[${tv[0]} , ${tv[1]}]`, "-->", count(tv[0], tv[1]))
}
Is it possible to create a numerical range in M? For example something like:
let
x = range(1,10) // {1,2,3,4,5,6,7,8,9,10}, from 1 to 10, increment by 1
x = range(1,10,2) // {1,3,5,7,9}, from 1 to 10, increment by 2
For simple scenarios, a..b might be appropriate. Some examples:
let
firstList = {1..10}, // {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
secondList = {1, 5, 12, 14..17, 18..20}, // {1, 5, 12, 14, 15, 16, 17, 18, 19, 20}
thirdList = {Character.ToNumber("a")..100, 110..112}, // {97, 98, 99, 100, 110, 111, 112}
fourthList = {95..(10 * 10)} // {95, 96, 97, 98, 99, 100}
in
fourthList
Otherwise, maybe try a custom function which internally uses List.Generate:
let
range = (inclusiveStart as number, inclusiveEnd as number, optional step as number) as list =>
let
interval = if step = null then 1 else step,
conditionFunc =
if (interval > 0) then each _ <= inclusiveEnd
else if (interval < 0) then each _ >= inclusiveEnd
else each false,
generated = List.Generate(() => inclusiveStart, conditionFunc, each _ + interval)
in generated,
firstList = range(1, 10), // {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
secondList = range(1, 10, 2), // {1, 3, 5, 7, 9}
thirdList = range(1, 10 , -1), // {} due to the combination of negative "step", but "inclusiveEnd" > "inclusiveStart"
fourthList = range(10, 1, 0), // {} current behaviour is to return an empty list if 0 is passed as "step" argument.
fifthList = range(10, 1, -1), // {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}
sixthList = range(10, 1, 1) // {} due to the combination of positive "step", but "inclusiveEnd" < "inclusiveStart"
in
sixthList
The above range function should be able to generate both ascending and descending sequences (see examples in code).
Alternatively, you could create a custom function which uses List.Numbers internally by first calculating what the count argument needs to be. But I chose to go with List.Generate.
I don't know which algorithm should I use. If it's necessary the platform is Node.js.
Volume = 100; Range = 5...15; N = 10.
I need to generate N numbers from Range that in sum will give Volume. What is the best way to do it?
Here's a quick, naive implementation.
There might be a numerical trick that allows making this faster, but this works. :)
Note that it's of course possible to pass in a combination of parameters that makes this function never complete, but for total = 100, min = 5, max = 15, n = 10 it does find solutions, e.g.
[ 14, 5, 11, 6, 10, 13, 9, 13, 14, 5 ]
[ 15, 13, 14, 10, 9, 8, 10, 8, 6, 7 ]
[ 8, 11, 11, 9, 12, 15, 5, 9, 6, 14 ]
[ 9, 12, 11, 6, 14, 12, 10, 7, 11, 8 ]
[ 9, 8, 9, 10, 11, 10, 12, 7, 14, 10 ]
[ 9, 9, 5, 14, 10, 13, 11, 13, 9, 7 ]
function generateNumbers(total, min, max, n) {
while (true) {
const numbers = [];
let sum = 0;
while (true) {
let num;
if (numbers.length === n - 1) {
// Fill in the last number with the remainder to satisfy the problem
num = total - sum;
if (num < min || num === 0 || num > max) {
// Out of bounds, this solution is invalid
break; // Try again.
}
} else {
num = Math.floor(min + Math.random() * (max + 1 - min));
}
numbers.push(num);
sum += num;
if (numbers.length === n && sum === total) {
// Solution found.
return numbers;
}
if (sum > total) {
// Overshot, retry.
break;
}
}
}
}
console.log(generateNumbers(100, 5, 15, 10));
I was trying to make a simulation of randomly picking number from 1-36, and to see how many time do I need to pick all the different 36 number. If I picked total of 10 duplicated number I can pick a number that has not been picked, and recount duplication.
Anyway, my code works fine if I only create one array contains random numbers. But I add a for loop outside of the whole process and repeat it 100 times in order to find out on average how many time do I need. And the code create 100 of same arrays.
#include "iostream"
#include "stdlib.h"
#include "time.h"
using namespace std;
class Lottery
{
private:
int PickNonExistingNum()//pick a number that's not in num
{
int pick;
pick = RandomNumber();
for (int m = 0; m < 36; m++)
{
if (pick == num[m])
{
pick = RandomNumber();
m = 0;
continue;
}
}
return pick;
}
public:
int check;
int TimeOfPicking = 0; //how many time we pick a number
int num[36] = { 0 }; //array contains all the number
bool same = false; //flag that indicates consistency
int accum = 0; //how many time we pick a same number, when reach 10 we pick again
bool IsRandomSeeded = false;
int i = 0; //used to change i value in for loop of main loop
int RandomNumber()//generate a number from 1 to 36
{
int number;
number = rand() % 36 + 1;
return number;
}
bool CheckExistingNum()
{
for (int k = 0; k < 36; k++)
{
if (check == num[k])
{
if (accum < 10)//add 1 to accum each time when there's a same number
{
i--;
accum++;
same = true;
break;
}
else if (accum == 10)//pick again when accum reach 10
{
num[i] = DoubleCheckPick(PickNonExistingNum());
accum = 0;
same = true;
break;
}
}
}
return same;
}
void Picking()
{
for (i; i < 36; i++)//finish the loop when player had picked all 36 numbers
{
check = RandomNumber();//give check a random value between 1 and 36
TimeOfPicking++; //add 1 time to the total time of picking
same = false; //set flag to false
if (!CheckExistingNum())//give checked value to num if there's no same number
{
num[i] = check;
}
}
cout << "Pick " << TimeOfPicking << " time" << endl;//show results
cout << "the numbers are:" << endl;
for (int m = 0; m < 36; m++)
{
cout << num[m] << ", ";
}
cout << endl;
}
bool DoubleCheck()
{
for (int m = 0; m < 36; m++)
{
for (int k = m + 1; k < 36; k++)
{
if (num[m] == num[k])
{
cout << "there's a same number: " << num[m] << endl << endl;
return false;
}
}
}
cout << "no same number" << endl << endl;
return true;
}
int DoubleCheckPick(int check)
{
for (int m = 0; m < 36; m++)
{
if (check == num[m])
{
check = PickNonExistingNum();
m = 0;
continue;
}
}
return check;
}
void reset()//reset all the value for multiple process
{
int TimeOfPicking = 0; //how many time we pick a number
int num[36] = { 0 }; //array contains all the number
int same = false; //flag that indicates consistency
int accum = 0; //how many time we pick a same number, when reach 10 we pick again
int check = 0;
int i = 0; //used to change i value in for loop of main loop
}
};
int main()
{
Lottery Num;
//int t = 0;
srand(time(NULL)); //set random generator
int PickingTime[100] = { 0 };//an array contains all 100 times of data
double sum = 0; //the sum of all the data
for (int i = 0; i < 100; i++)//run the program 100 times
{
cout << "the " << i + 1 << " process" << endl;
int wait = clock();
while (clock() <= (wait + 1000));//delay for 3000 unit time
Num.reset();
Num.Picking();
if (!Num.DoubleCheck())//if there's a same number
{
cout << "fail process" << endl;
i--; //redo the process
continue;
}
else
{
PickingTime[i] = Num.TimeOfPicking;
}
}
for (int i = 0; i < 100; i++)
{
sum += PickingTime[i];
}
cout << "the average picking time in 100 test is: " << sum / 100 << endl;
return 0;
}
and the result looks like this result
all the arrays are the same. I guess it might be the rand() problem, but I can't find any solution that will work.
Your reset() function did not actually reset the class variables - it defined new local ones. So the subsequent calls to Picking() didn't do anything for i was already 36. Change it to the following:
void reset()//reset all the value for multiple process
{
TimeOfPicking = 0; //how many time we pick a number
//int num[36] = { 0 }; //No need to reset the array - it will be overriden in the later invocation of Picking()
same = false; //flag that indicates consistency
accum = 0; //how many time we pick a same number, when reach 10 we pick again
check = 0;
i = 0; //used to change i value in for loop of main loop
}
And you get different number sequences each time.
Note that your CheckExistingNum() must be fixed too for this to work - change for (int k = 0; k < 36; k++) to for (int k = 0; k < i; k++) to only check the numbers generated in the current loop, not old ones. This is required because we don't reset num in reset() (to set it to all zero anywhere other than initialization, you must use a loop or memset()). And it also make your program faster.
After the 2 fixes, I got the following output,
......
the 98 process
Pick 76 time
the numbers are:
26, 9, 4, 36, 32, 12, 16, 7, 17, 33, 1, 10, 18, 2, 23, 21, 28, 29, 30, 25, 8, 34, 27, 31, 14, 24, 11, 20, 6, 22, 3, 15, 19, 5, 13, 26,
there's a same number: 26
fail process
the 98 process
Pick 76 time
the numbers are:
17, 3, 15, 7, 31, 12, 26, 24, 9, 13, 4, 32, 29, 11, 20, 14, 23, 1, 33, 18, 8, 27, 21, 19, 25, 6, 30, 36, 2, 5, 28, 34, 22, 35, 16, 10,
no same number
the 99 process
Pick 106 time
the numbers are:
10, 11, 9, 28, 36, 15, 18, 8, 13, 34, 30, 3, 12, 21, 16, 1, 2, 27, 19, 23, 17, 5, 20, 14, 4, 25, 6, 29, 7, 22, 33, 26, 32, 24, 31, 35,
no same number
the 100 process
Pick 106 time
the numbers are:
15, 23, 22, 11, 5, 35, 2, 26, 21, 4, 3, 33, 28, 19, 1, 14, 7, 29, 24, 32, 8, 12, 13, 27, 10, 17, 34, 18, 16, 6, 25, 20, 31, 36, 30, 9,
no same number
Try it out! You could further optimize the program, which is left as an exercise. :)
I have a method which does a series of calculations which take quite a bit of time to complete. The objects that this method does computations on are generated at runtime and can range from a few to a few thousand. Obviously it would be better if I could run these computations across several threads concurrently, but when I try that, my program uses more CPU yet takes longer than running them one-by-one. Any ideas why?
let itemsPerThread = (dataArray.count / 4) + 1
for var i = 0; i < dataArray.count; i += itemsPerThread
{
let name = "ComputationQueue\(i)".bridgeToObjectiveC().cString()
let compQueue = dispatch_queue_create(name, DISPATCH_QUEUE_CONCURRENT)
dispatch_async(compQueue,
{
let itemCount = i + itemsPerThread < dataArray.count ? itemsPerThread : dataArray.count - i - 1
let subArray = dataArray.bridgeToObjectiveC().subarrayWithRange(NSMakeRange(i, dataCount)) as MyItem[]
self.reallyLongComputation(subArray, increment: increment, outputIndex: self.runningThreads-1)
})
NSThread.sleepForTimeInterval(1)
}
Alternatively:
If I run this same thing, but a single dispatch_async call and on the whole dataArray rather than the subarrays, it completes much faster while using less CPU.
what you (it is my guess) want to do should looks like
//
// main.swift
// test
//
// Created by user3441734 on 12/11/15.
// Copyright © 2015 user3441734. All rights reserved.
//
import Foundation
let computationGroup = dispatch_group_create()
var arr: Array<Int> = []
for i in 0..<48 {
arr.append(i)
}
print("arr \(arr)")
func job(inout arr: Array<Int>, workers: Int) {
let count = arr.count
let chunk = count / workers
guard chunk * workers == count else {
print("array.cout divided by workers must by integer !!!")
return
}
let compQueue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT)
let syncQueue = dispatch_queue_create("aupdate", DISPATCH_QUEUE_SERIAL)
for var i = 0; i < count; i += chunk
{
let j = i
var tarr = arr[j..<j+chunk]
dispatch_group_enter(computationGroup)
dispatch_async(compQueue) { () -> Void in
for k in j..<j+chunk {
// long time computation
var z = 100000000
repeat {
z--
} while z > 0
// update with chunk
tarr[k] = j
}
dispatch_async(syncQueue, { () -> Void in
for k in j..<j+chunk {
arr[k] = tarr[k]
}
dispatch_group_leave(computationGroup)
})
}
}
dispatch_group_wait(computationGroup, DISPATCH_TIME_FOREVER)
}
var stamp: Double {
return NSDate.timeIntervalSinceReferenceDate()
}
print("running on dual core ...\n")
var start = stamp
job(&arr, workers: 1)
print("job done by 1 worker in \(stamp-start) seconds")
print("arr \(arr)\n")
start = stamp
job(&arr, workers: 2)
print("job done by 2 workers in \(stamp-start) seconds")
print("arr \(arr)\n")
start = stamp
job(&arr, workers: 4)
print("job done by 4 workers in \(stamp-start) seconds")
print("arr \(arr)\n")
start = stamp
job(&arr, workers: 6)
print("job done by 6 workers in \(stamp-start) seconds")
print("arr \(arr)\n")
with results
arr [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
running on dual core ...
job done by 1 worker in 5.16312199831009 seconds
arr [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
job done by 2 workers in 2.49235796928406 seconds
arr [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]
job done by 4 workers in 3.18479603528976 seconds
arr [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36]
job done by 6 workers in 2.51704299449921 seconds
arr [0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40]
Program ended with exit code: 0
... you can use next pattern for distributing job between any number of workers (the number of workers which give you the best performance depends on worker definition and sources which are available in your environment). generally for any kind of long time calculation ( transformation ) you can expect some performance gain. in two core environment up to 50%. if your worker use highly optimized functions using more cores 'by default', the performance gain can be close to nothing :-)
// generic implementation
// 1) job distribute data between workers as fair, as possible
// 2) workers do their task in parallel
// 3) the order in resulting array reflect the input array
// 4) there is no requiremets of worker block, to return
// the same type as result of yor 'calculation'
func job<T,U>(arr: [T], workers: Int, worker: T->U)->[U] {
guard workers > 0 else { return [U]() }
var res: Dictionary<Int,[U]> = [:]
let workersQueue = dispatch_queue_create("workers", DISPATCH_QUEUE_CONCURRENT)
let syncQueue = dispatch_queue_create("sync", DISPATCH_QUEUE_SERIAL)
let group = dispatch_group_create()
var j = min(workers, arr.count)
var i = (0, 0, arr.count)
var chunk: ArraySlice<T> = []
repeat {
let a = (i.1, i.1 + i.2 / j, i.2 - i.2 / j)
i = a
chunk = arr[i.0..<i.1]
dispatch_group_async(group, workersQueue) { [i, chunk] in
let arrs = chunk.map{ worker($0) }
dispatch_sync(syncQueue) {[i,arrs] in
res[i.0] = arrs
}
}
j--
} while j != 0
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
let idx = res.keys.sort()
var results = [U]()
idx.forEach { (idx) -> () in
results.appendContentsOf(res[idx]!)
}
return results
}
You need to
Get rid of the 1 second sleep. This is artifically reducing the degree to which you get parallel execution, because you're waiting before starting the next thread. You are starting 4 threads - and you are therefore artifically delaying the start (and potentially the finish) of the final thread by 3 seconds.
Use a single concurrent queue, not one per dispatch block. A concurrent queue will start blocks in the order in which they are dispatched, but does not wait for one block to finish before starting the next one - i.e. it will run blocks in parallel.
NSArray is a thread-safe class. I presume that it uses a multiple-reader/single-writer lock internally, which means there is probably no advantage to be obtained from creating a set of subarrays. You are, however, incurring the overhead of creating the subArray
Multiple threads running on different cores cannot talk to the same cache line at the same time.Typical cache line size is 64 bytes, which seems unlikely to cause a problem here.