Related
I have four arrays of int:
num_defect = [30, 30, 20, 20, 18, 18, 5, 5]
num_fixes = [1, 0, 3, 2, 1, 2, 2, 2]
num_blocks = [0, 0, 0, 0, 2, 2, 1, 0]
num_ext_defects = [1, 1, 0, 0, 2, 2, 2, 1]
I want to display the number of open defects, which is given by:
num_defects - num_fixes - num_blocks - num_ext_defects
So for the reporting, num_defects should now contain:
[28, 29, 17, 13, 12, 0, 2]
I tried:
num_defect.map { |i| i - num_fixes[i] - num_blocks[i] - num_ext_defects[i] }
but it raises:
nil can't be coerced into Fixnum
Any help greatly appreciated.
With
num_defect.map { |i|
i is the element of the array, not its index. If you want your map to work correctly, you'll need an index as well:
num_defect.map.with_index do |element, index|
element - num_fixes[index] - num_blocks[index] - num_ext_defects[index]
end
Use map! instead of map in order to mutate num_defect.
Or if you'd like a nicer version:
a = [30,30,20,20,18,18,5,5]
b = [ 1, 0, 3, 2, 1, 2,2,2]
c = [ 0, 0, 0, 0, 2, 2,1,0]
d = [ 1, 1, 0, 0, 2, 2,2,1]
a.zip(b,c,d).map { |arr| arr.inject(:-) }
# => [28, 29, 17, 18, 13, 12, 0, 2]
If i understand you correctly you might be looking for an array method called each_index.
num_defect.each_index do |i|
num_defect[i] -= num_fixes[i] + num_blocks[i] + num_ext_defects[i]
end
require 'matrix'
(Vector.elements(num_defect) - Vector.elements(num_fixes) -
Vector.elements(num_blocks) - Vector.elements(num_ext_defects)).to_a
#=> [28, 29, 17, 18, 13, 12, 0, 2]
This uses the methods Vector::elements and Vector#to_a. One could write Vector[*arr] in place of Vector.elements(arr), using Vector::[].
If num_defect is to be mutated, you could write num_defect.replace(<above expression>). If
arr = [num_defect, num_fixes, num_blocks, num_ext_defects]
#=> [[30, 30, 20, 20, 18, 18, 5, 5],
# [ 1, 0, 3, 2, 1, 2, 2, 2],
# [ 0, 0, 0, 0, 2, 2, 1, 0],
# [ 1, 1, 0, 0, 2, 2, 2, 1]]
one could use matrix multiplication:
(Matrix.row_vector([1, *[-1]*(arr.size-1)]) * Matrix.rows(arr)).to_a.first
#=> [28, 29, 17, 18, 13, 12, 0, 2]
where
[1, *[-1]*(arr.size-1)]
#=> [1, -1, -1, -1]
This would be convenient and relatively computationally-efficient if arr had a larger number of elements than it does in the example.
This uses the Matrix methods Matrix::row_vector, Matrix::rows and Matrix#to_a. One could write Matrix[*arr] in place of Matrix.rows(arr), using Matrix::[]. One advantage of using rows, however, is that one can add the argument false (Matrix.rows(arr, false)) to avoid copying the elements of arr in the creation of the Matrix object.
[num_defect, num_fixes, num_blocks, num_ext_defects]
.transpose
.map{|first, *rest| first - rest.sum}
# => [28, 29, 17, 18, 13, 12, 0, 2]
Using Enumerator#each_with_object:
num_defect.each_with_index.with_object([]){ |(e, i), a| a << (e - num_fixes[i] - num_blocks[i] - num_ext_defects[i]) }
#=> [28, 29, 17, 18, 13, 12, 0, 2]
I just have a question,
I have been building alexa skill. (the Concept is Randomize Positivity)
but somehow it keep returning the same sentence....
this is my code...
` for (var j = 0; j < index; j++){
var rand = Math.floor(Math.random() * index);
index -= 1;
var temp = indexList[index];
indexList[index] = indexList[rand];
indexList[rand] = temp;
}`// I also swap the words so It would sure not to return the same but somehow it happens..
and the index is about 15 strings for now...
my Question is how do I make it random as possible?
You're just trying to shuffle an array, right? See the Fisher-Yates shuffle. You're already almost doing the same thing.
I tried this and it worked fine.
var indexList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var rand;
var temp;
for (let i = 0; i < indexList.length; i++) {
rand = Math.floor(Math.random() * (i + 1));
temp = indexList[i];
indexList[i] = indexList[rand];
indexList[rand] = temp;
console.log(indexList);
}
It printed the following, showing that it is shuffling the array more and more each step:
> Array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [3, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [4, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [4, 1, 5, 3, 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 1, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 1, 7, 8, 9, 10, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 8, 7, 1, 9, 10, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 8, 9, 1, 7, 10, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 8, 9, 1, 10, 7, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 8, 9, 1, 10, 7, 11, 12, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 8, 9, 1, 12, 7, 11, 10, 13, 14, 15]
> Array [4, 6, 5, 3, 2, 8, 9, 1, 12, 7, 11, 10, 13, 14, 15]
> Array [4, 6, 14, 3, 2, 8, 9, 1, 12, 7, 11, 10, 13, 5, 15]
> Array [4, 6, 15, 3, 2, 8, 9, 1, 12, 7, 11, 10, 13, 5, 14]
I want to use eratosthenes method
to get prime numbers with swift. I create first function to return new array without those numbers that can be divided for specific multiplier, then create second function to create new array every time with new P multiplier. I wonder why its not work (look like it somehow pass old array, i dont know why). It should print new array of prime numbers at the end:
var simpleArr : [Int] = []
for i in 2...100 {
simpleArr.append(i)
}
func arrayEcludingDivingByP (p: Int, arrToCheck : [Int]) -> Array<Int>{
var tmp : [Int] = []
for (ob, index) in arrToCheck.enumerated() {
var isDividible : Bool = ob % p == 0 ? true : false
if (!isDividible){
tmp.append(ob)
}
}
return tmp
}
var p : Int = 2
func getSimpleNumbersArrayFromArray (p : Int, arrPassed : [Int]) -> Array <Int>{
var tmp : [Int] = []
var newArr = arrayEcludingDivingByP(p: p, arrToCheck: arrPassed)
if (newArr.isEmpty){
// No more p availible, just return tmp
} else {
let newP = p + 1
getSimpleNumbersArrayFromArray(p: newP, arrPassed: newArr)
tmp = newArr
print("tmp array? \(tmp)")
}
return tmp
}
getSimpleNumbersArrayFromArray(p: p, arrPassed: simpleArr)
In console it prints:
tmp array? [1]
tmp array? [1, 2]
tmp array? [1, 2, 3]
tmp array? [1, 2, 3, 4]
tmp array? [1, 2, 3, 4, 5]
tmp array? [1, 2, 3, 4, 5, 6]
tmp array? [1, 2, 3, 4, 5, 6, 7]
tmp array? [1, 2, 3, 4, 5, 6, 7, 8]
tmp array? [1, 2, 3, 4, 5, 6, 7, 9, 10, 11]
tmp array? [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]
tmp array? [1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17]
tmp array? [1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 21, 22, 23]
tmp array? [1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18, 19, 21, 22, 23, 25, 26, 27, 29, 30, 31]
tmp array? [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47]
tmp array? [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97]
But it suppose to print final iteration with tmp filled with prime numbers. What did i wrong?
You are using newArr to represent the values in the sieve that remain. Your tmp array should be the primes found so far. Also you are using a recursive call which is confusing. I suggest simply grabbing the first value out of newArr which is a prime, add that prime to your list of primes, and then call arrayEcludingDividingByP to filter out the non-primes divisible by that prime. Repeat until newArr isEmpty which will happen when the conditional binding statement while let newP = newArr.first fails and the loop ends:
func getPrimes(arrPassed: [Int]) -> [Int] {
var primes: [Int] = []
var newArr = arrPassed
while let newP = newArr.first {
primes.append(newP)
newArr = arrayEcludingDivingByP(p: newP, arrToCheck: newArr)
}
return primes
}
print(getPrimes(arrPassed: Array(2...100)))
This can be further optimized because once newP * newP is greater than the largest number in newArr (newArr.last!) you are done and you can simply append newArr to primes and set newArr to [].
Also, arrayEcludingDivingByP(p: newP, arrToCheck: newArr) can be replaced by newArr.filter { $0 % newP != 0 }
I wrote the following code in a playground and it works fine, but it seems a little messy. Is there a more concise way of writing this in Swift?
I want a string to look like the following:
1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14
I will not know how many values in each array and the arrays may not be even multiples, but I will know the relationship of 3 array1 values for each array2 value
let array1 = [1,2,3,4,5,6,7,8] //sample 1st array
let array2 = [12,13,14] //sample 2nd array
let relationshipInterval = 3
let remainder = (array1.count % relationshipInterval)
let multiples = (array1.count - remainder)/relationshipInterval
var string = ""
var array1Start = 0
var array1End = relationshipInterval-1
var array2Value = 0
for _ in 1...multiples {
for array1value in array1[array1Start...array1End] {
string += "\(array1value), "
string += String(array2[array2Value])+", "
}
array1Start = array1End + 1
array1End = array1Start + relationshipInterval - 1
array2Value += 1
}
for array1value in array1[array1Start...array1Start+remainder-1] {
string += "\(array1value), "
string += String(array2[array2Value])+", "
}
print (string) //prints 1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14
I'm not sure if this covers all of the use cases, but using zip, flatMap, and joined you do this in a single step!
let array1 = [1,2,3,4,5,6,7,8]
let array2 = [12, 13, 14]
let text = zip(array1, array2.flatMap({ [$0, $0, $0] }))
.flatMap({ [$0, $1] })
.map({ String($0) })
.joined(separator: ", ")
// text -> "1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14"
Here's that one-liner broken into four steps so it's clearer what's happening at each stage:
// 1. create an array with each element in array2 is trippled:
let trippled = array2.flatMap({ item in
return [item, item, item]
})
// trippled -> [12, 12, 12, 13, 13, 13, 14, 14, 14]
// 2. zip array1 with the trippled array:
let zipped = zip(array1, trippled)
// zipped -> Zip2Sequence(_sequence1: [1, 2, 3, 4, 5, 6, 7, 8], _sequence2: [12, 12, 12, 13, 13, 13, 14, 14, 14])
// 3. flatten the zipped aray
let combined = zipped.flatMap({ leftItem, rightItem in
return [leftItem, rightItem]
})
// combined -> [1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14]
// 4. tranform to a string
let text = combined.map({ item in
return "\(item)"
}).joined(separator: ", ")
// text -> "1, 12, 2, 12, 3, 12, 4, 13, 5, 13, 6, 13, 7, 14, 8, 14"
How to select every n-elements (e.g. six) of an array using Ruby 1.9+? Example:
a = [0, 1, 2, 3, 4, ... , 33]
# solution
# => [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], ... ]
Enumerable#each_slice
Iterates the given block for each
slice of elements. If no block is
given, returns an enumerator.
e.g.:
(1..10).each_slice(3) {|a| p a}
# outputs below
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10]
Use as:
irb(main):002:0> a = Array(1..33)
=> [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]
irb(main):003:0> a.each_slice(5) # no good
=> #<Enumerable::Enumerator:0x47ae6e8>
irb(main):004:0> a.each_slice(5).to_a # good
=> [[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]]