I try to write and read from Arrays (from different arrays) in Swift in concurrent way, and have exception in the runtime on write operation.
I have concurrent blur code in Objective-C++:
- (cpp_blur::Bitmap)blur {
Bitmap result(_source);
auto indexes = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _source.size())];
int minIndex = 0;
int maxIndex = static_cast<int>(result.size()) - 1;
[indexes enumerateIndexesWithOptions:NSEnumerationConcurrent
usingBlock:[&](NSUInteger idx, BOOL* _Nonnull stop){
double sum = 0.0;
for (int i = static_cast<int>(idx) - static_cast<int>(self.radius); i <= idx + self.radius; i++) {
int index = clamp(i, minIndex, maxIndex);
sum += self->_source.at(index);
}
sum /= static_cast<double>(self.radius * 2 + 1);
result.at(idx) = sum;
}];
return result;
}
I try to write same code in Swift:
#objc public func blur() -> [Double] {
var result = source
let indexSet = NSIndexSet(indexesIn: NSMakeRange(0, source.count))
let from = -Int(self.blurRadius)
let to = Int(self.blurRadius)
let lastIndex = self.source.count - 1
indexSet.enumerate(options: .concurrent) { (index:Int, _) in
let sum = ((from + index)...(to + index)).reduce(0.0) { (partial:Double, nonClamped:Int) -> Double in
let index = self.clamp(nonClamped, min: 0, max: lastIndex)
let result = partial + self.source[index]
return result
}
let avg = sum / Double(2 * self.blurRadius + 1);
result[index] = avg //here I have crash in runtime
}
return result
}
If I add a lock around result[index] = avg, this exception will move away, but I will have performance issue.
How I can change values of elements in Swift Array without lock (In same time I change only different elements)?
Github repo.
This question already has answers here:
How can I sort multiple arrays based on the sorted order of another array
(2 answers)
Closed 6 years ago.
Say I have and array [4, 1, 8, 5] and another array that corresponds to each object in the first array, say ["Four", "One", "Eight", "Five"]. How can I sort the first array in ascending order while also moving the corresponding object in the second array to the same index in Swift?
Doesn't sound like best practice but this will solve your problem:
var numbers = [4,7,8,3]
var numbersString = ["Four","Seven","Eight","Three"]
func bubbleSort<T,Y>(inout numbers:[T],inout _ mirrorArray: [Y], _ comapre : (T,T)->(Bool)) -> () {
let numbersLength = numbers.count
for i in 0 ..< numbersLength {
for j in 1 ..< numbersLength-i {
if comapre(numbers[j-1],numbers[j]) {
swap(&numbers[j-1], &numbers[j])
swap(&mirrorArray[j-1], &mirrorArray[j])
}
}
}
}
bubbleSort(&numbers,&numbersString) { (a, b) -> (Bool) in
a<b
}
print(numbers,numbersString)
*This is generic therefore will work with any type and let you supply the condition
Using quick sort:
func quicksort_swift(inout a:[Int], inout b:[String], start:Int, end:Int) {
if (end - start < 2){
return
}
let p = a[start + (end - start)/2]
var l = start
var r = end - 1
while (l <= r){
if (a[l] < p){
l += 1
continue
}
if (a[r] > p){
r -= 1
continue
}
let t = a[l]
let t1 = b[l]
a[l] = a[r]
b[l] = b[r]
a[r] = t
b[r] = t1
l += 1
r -= 1
}
quicksort_swift(&a, b: &b, start: start, end: r + 1)
quicksort_swift(&a, b: &b, start: r + 1, end: end)
}
Although, the dictionary solution offered by #NSNoob, should be faster and more elegant.
What is the problem with the following function to receive and execute:
func FibFast(num: Int) -> Array<Int> {
var fib_arr = [Int](num)
if num < 1 {
fib_arr[0] = 0
return fib_arr
} else if num < 2 {
fib_arr[1] = 1
return fib_arr
}else {
for var i = 2; i < num; i++ {
fib_arr[i] = fib_arr[i-1] + fib_arr[i-2]
}
return fib_arr
}
}
when I am trying to receive the array like:
var newArray = FibFast(10)
it's producing a bad execution.
You are attempting to subscript the array with indexes that don't exist, similarly in your else case you are trying to subscript to an index of 2 when the array is empty.
the line var fib_arr = [Int]() creates an empty array on integers. when you use fib_arr[0] = 0 you are trying to assign the value at index 0 to have a value of 0 but no value currently exists. I would recommend using the append(_) method ie. fib_arr.append(0).
Also when you pass in a value of 10 or anything that is 2 or more as the num parameter your if-else if-else statement is executing the for loop where you are attempting to access the index of 0 and 1 which have not been set as the earlier statements were never executed as they were skipped by the if-else if-else block.
The for loop and assign the values with subscripts is very indicative of the fact that you've probably learnt a different language before swift. You should note that the classic c-style for loop you are trying to use will be removed from swift soon so its better to get in the habbit of no using it. Ive rewritten your code as close to the way you wrote yours, please don't hesitate to ask if you have any questions about it.
func fib(num: Int) -> [Int] {
var fib_arr = [Int]()
if num == 0 {
fib_arr.append(0)
} else if num == 1 {
fib_arr.append(0)
fib_arr.append(1)
} else {
fib_arr = [0, 1]
for i in 2..<num {
fib_arr.append(fib_arr[i - 1] + fib_arr[i - 2])
}
}
return fib_arr
}
The answer proposed by Blake Lockley can also be coded like this:
func FibFast(num: Int) -> Array<Int> {
var fib_arr = [Int]() // empty array
if num < 1 {
fib_arr += [0] // add element [0]
return fib_arr
} else if num < 2 {
fib_arr += [0] // add element [0]
fib_arr += [1] // add element [1]
return fib_arr
}else {
fib_arr = [0, 1] // init with [0, 1]
for var i = 2; i < num; i++ {
// add computed element
fib_arr += [fib_arr[i-1] + fib_arr[i-2]]
}
return fib_arr
}
}
I have seen this question for other languages but not for AS3... and I'm having a hard time understanding it...
I need to generate 3 numbers, randomly, from 0 to 2, but they cannot repeat (as in 000, 001, 222, 212 etc) and they cannot be in the correct order (0,1,2)...
Im using
for (var u: int = 0; u < 3; u++)
{
mcCor = new CorDaCarta();
mcCor.x = larguraTrio + (mcCor.width + 5) * (u % 3);
mcCor.y = alturaTrio + (mcCor.height + 5) * (Math.floor(u / 3));
mcCor.gotoAndStop((Math.random() * (2 - u + 1) + u) | 0); // random w/ repeats
//mcCor.gotoAndStop(Math.floor(Math.random() * (2 - u + 1) + u)); // random w/ repeats
//mcCor.gotoAndStop((Math.random() * 3) | 0); // crap....
//mcCor.gotoAndStop(Math.round(Math.random()*u)); // 1,1,1
//mcCor.gotoAndStop(u + 1); // 1,2,3
mcCor.buttonMode = true;
mcCor.addEventListener(MouseEvent.CLICK, cliquetrio);
mcExplic.addChild(mcCor);
trio.push(mcCor);
}
those are the codes i've been trying.... best one so far is the active one (without the //), but it still gives me duplicates (as 1,1,1) and still has a small chance to come 0,1,2....
BTW, what I want is to mcCor to gotoAndStop on frames 1, 2 or 3....without repeating, so THE USER can put it on the right order (1,2,3 or (u= 0,1,2), thats why I add + 1 sometimes there)
any thoughts?? =)
I've found that one way to ensure random, unique numbers is to store the possible numbers in an array, and then sort them using a "random" sort:
// store the numbers 0, 1, 2 in an array
var sortedNumbers:Array = [];
for(var i:int = 0; i < 3; i++)
{
sortedNumbers.push(i);
}
var unsortedNumbers:Array = sortedNumbers.slice(); // make a copy of the sorted numbers
trace(sortedNumbers); // 0,1,2
trace(unsortedNumbers); // 0,1,2
// randomly sort array until it no longer matches the sorted array
while(sortedNumbers.join() == unsortedNumbers.join())
{
unsortedNumbers.sort(function (a:int, b:int):int { return Math.random() > .5 ? -1 : 1; });
}
trace(unsortedNumbers); // [1,0,2], [2,1,0], [0,1,2], etc
for (var u: int = 0; u < 3; u++)
{
mcCor = new CorDaCarta();
mcCor.x = larguraTrio + (mcCor.width + 5) * (u % 3);
mcCor.y = alturaTrio + (mcCor.height + 5) * (Math.floor(u / 3));
// grab the corresponding value from the unsorted array
mcCor.gotoAndStop(unsortedNumbers[u] + 1);
mcCor.buttonMode = true;
mcCor.addEventListener(MouseEvent.CLICK, cliquetrio);
mcExplic.addChild(mcCor);
trio.push(mcCor);
}
Marcela is right. Approach with an Array is widely used for such task. Of course, you will need to check 0, 1, 2 sequence and this will be ugly, but in common code to get the random sequence of integers can look like this:
function getRandomSequence(min:int, max:int):Array
{
if (min > max) throw new Error("Max value should be greater than Min value!");
if (min == max) return [min];
var values:Array = [];
for (var i:int = min; i <= max; i++) values.push(i);
var result:Array = [];
while (values.length > 0) result = result.concat(values.splice(Math.floor(Math.random() * values.length), 1));
return result;
}
for (var i:uint = 0; i < 10; i++)
{
trace(getRandomSequence(1, 10));
}
You will get something like that:
2,9,3,8,10,6,5,1,4,7
6,1,2,4,8,9,5,10,7,3
3,9,10,6,8,2,5,4,1,7
7,6,1,4,3,8,9,2,10,5
4,6,7,1,3,2,9,10,8,5
3,10,5,9,1,7,2,4,8,6
1,7,9,6,10,3,4,5,2,8
4,10,8,9,3,2,6,1,7,5
1,7,8,9,10,6,4,3,2,5
7,5,4,2,8,6,10,3,9,1
I created this for you. It is working but it can be optimized...
Hope is good for you.
var arr : Array = [];
var r : int;
for (var i: int = 0; i < 3; i++){
r=rand(0,2);
if(i == 1){
if(arr[0] == r){
i--;
continue;
}
if(arr[0] == 0){
if(r==1){
i--;
continue;
}
}
}else if(i==2){
if(arr[0] == r || arr[1] == r){
i--;
continue;
}
}
arr[i] = r;
}
trace(arr);
for(var i=0;i<3;i++){
mcCor = new CorDaCarta();
mcCor.x = larguraTrio + (mcCor.width + 5) * (i % 3);
mcCor.y = alturaTrio + (mcCor.height + 5) * (Math.floor(i / 3));
mcCor.gotoAndStop(arr[i]);
mcCor.buttonMode = true;
mcCor.addEventListener(MouseEvent.CLICK, cliquetrio);
mcExplic.addChild(mcCor);
trio.push(mcCor);
}
function rand(min:int, max:int):int {
return Math.round(Math.random() * (max - min) + min);
}
try this...
I was trying to solve Project Euler problem number 7 using scala 2.8
First solution implemented by me takes ~8 seconds
def problem_7:Int = {
var num = 17;
var primes = new ArrayBuffer[Int]();
primes += 2
primes += 3
primes += 5
primes += 7
primes += 11
primes += 13
while (primes.size < 10001){
if (isPrime(num, primes)) primes += num
if (isPrime(num+2, primes)) primes += num+2
num += 6
}
return primes.last;
}
def isPrime(num:Int, primes:ArrayBuffer[Int]):Boolean = {
// if n == 2 return false;
// if n == 3 return false;
var r = Math.sqrt(num)
for (i <- primes){
if(i <= r ){
if (num % i == 0) return false;
}
}
return true;
}
Later I tried the same problem without storing prime numbers in array buffer. This take .118 seconds.
def problem_7_alt:Int = {
var limit = 10001;
var count = 6;
var num:Int = 17;
while(count < limit){
if (isPrime2(num)) count += 1;
if (isPrime2(num+2)) count += 1;
num += 6;
}
return num;
}
def isPrime2(n:Int):Boolean = {
// if n == 2 return false;
// if n == 3 return false;
var r = Math.sqrt(n)
var f = 5;
while (f <= r){
if (n % f == 0) {
return false;
} else if (n % (f+2) == 0) {
return false;
}
f += 6;
}
return true;
}
I tried using various mutable array/list implementations in Scala but was not able to make solution one faster. I do not think that storing Int in a array of size 10001 can make program slow. Is there some better way to use lists/arrays in scala?
The problem here is that ArrayBuffer is parameterized, so what it really stores are references to Object. Any reference to an Int is automatically boxed and unboxed as needed, which makes it very slow. It is incredibly slow with Scala 2.7, which uses a Java primitive to do that, which does it very slowly. Scala 2.8 takes another approach, making it faster. But any boxing/unboxing will slow you down. Furthermore, you are first looking up the ArrayBuffer in the heap, and then looking up again for java.lang.Integer containing the Int -- two memory accesses, which makes it way slower than your other solution.
When Scala collections become specialized, it should be plenty faster. Whether it should be enough to beat your second version or not, I don't know.
Now, what you may do to get around that is to use Array instead. Because Java's Array are not erased, you avoid the boxing/unboxing.
Also, when you use for-comprehensions, your code is effectively stored in a method which is called for each element. So you are also making many method calls, which is another reason this is slower. Alas, someone wrote a plugin for Scala which optimizes at least one case of for-comprehensions to avoid that.
Using Array should make it work in about zero seconds with the right algorithm. This, for example, takes about 7 milliseconds on my system:
class Primes(bufsize: Int) {
var n = 1
val pbuf = new Array[Int](bufsize max 1)
pbuf(0) = 2
def isPrime(num: Int): Boolean = {
var i = 0
while (i < n && pbuf(i)*pbuf(i) <= num) {
if (num % pbuf(i) == 0) return false
i += 1
}
if (pbuf(i)*pbuf(i) < num) {
i = pbuf(i)
while (i*i <= num) {
if (num % i == 0) return false
i += 2
}
}
return true;
}
def fillBuf {
var i = 3
n = 1
while (n < bufsize) {
if (isPrime(i)) { pbuf(n) = i; n += 1 }
i += 2
}
}
def lastPrime = { if (n<bufsize) fillBuf ; pbuf(pbuf.length-1) }
}
object Primes {
def timedGet(num: Int) = {
val t0 = System.nanoTime
val p = (new Primes(num)).lastPrime
val t1 = System.nanoTime
(p , (t1-t0)*1e-9)
}
}
Result (on second call; first has some overhead):
scala> Primes.timedGet(10001)
res1: (Int, Double) = (104743,0.00683394)
I think you have to think out of the box :)
Because the problem is manageable, you can use Sieve of Eratosthenes to solve it very efficiently.
Here's a recursive solution (using the isPrime function from your first solution). It seems to be good Scala style to prefer immutability (i.e. to try not to use vars) so I've done that here (in fact there are no vars or vals!). I don't have a Scala installation here though so can't tell if this is actually any quicker!
def problem_7:Int = {
def isPrime_(n: Int) = (n % 6 == 1 || n % 6 == 5) && isPrime(n)
def process(n: Int, acc: List[Int]): Int = {
if (acc.size == 10001) acc.head
else process(n+1, if isPrime_(n) n :: acc else acc)
}
process(1, Nil)
}