Related
I want to compare each element against all others like following. The number of variables like a, b, c is dynamic. However, each variable's array size is uniform.
let a = [1, 2, 3]
let b = [3, 4, 5]
let c = [4, 5, 6]
for i in a {
for j in b {
for k in c {
/// comparison
}
}
}
Instead looping from start to finish at once, what would be a way to make each comparison on call? For example:
compare(iteration: 0)
/// compares a[0], b[0], c[0]
compare(iteration: 1)
/// compares a[0], b[0], c[1]
/// all the way to
/// compares a[2], b[2], c[2]
Or it could even be like following:
next()
/// compares a[0], b[0], c[0]
next()
/// compares a[0], b[0], c[1]
almost like an iterator stepping through each cycle dictated by my invocation.
Let the number of arrays be n. And let the number of elements in each array, which is guaranteed the same for all of them, be k.
Then create an array consisting of the integers 0 through k-1, repeated n times. For example, in your case, n is 3, and k is 3, so generate the array
[0, 1, 2, 0, 1, 2, 0, 1, 2]
Now obtain all combinations of n elements of that array. You can do this using the algorithm at https://github.com/apple/swift-algorithms/blob/main/Guides/Combinations.md. Unique the result (by, for example, coercing to a Set and then back to an Array). This will give you a result equivalent, in some order or other, to
[[0, 1, 2], [0, 1, 0], [0, 1, 1], [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 0, 1], [0, 0, 2], [0, 0, 0], [1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 0, 1], [1, 0, 2], [1, 0, 0], [1, 1, 2], [1, 1, 0], [1, 1, 1], [2, 0, 1], [2, 0, 2], [2, 0, 0], [2, 1, 2], [2, 1, 0], [2, 1, 1], [2, 2, 0], [2, 2, 1], [2, 2, 2]]
You can readily see that those are all 27 possible combinations of the numbers 0, 1, and 2. But that is exactly what you were doing with your for loops! So now, use those subarrays as indexes into each of your original arrays respectively.
So for instance, using my result and your original example, the first subarray [0, 1, 2] yields [1, 4, 6] — the first value from the first array, the second value from the second array, and the third value from the third array. And so on.
In this way you will have generated all possible n-tuples by choosing one value from each of your original arrays, which is the desired result; and we are in no way bound to fixed values of n and k, which was what you wanted to achieve. You will then be able to "compare" the elements of each n-tuple, whatever that may mean to you (you did not say in your question what it means).
In the case of your original values, we will get these n-tuples (expressed as arrays):
[1, 4, 6]
[1, 4, 4]
[1, 4, 5]
[1, 5, 4]
[1, 5, 5]
[1, 5, 6]
[1, 3, 5]
[1, 3, 6]
[1, 3, 4]
[2, 5, 4]
[2, 5, 5]
[2, 5, 6]
[2, 3, 5]
[2, 3, 6]
[2, 3, 4]
[2, 4, 6]
[2, 4, 4]
[2, 4, 5]
[3, 3, 5]
[3, 3, 6]
[3, 3, 4]
[3, 4, 6]
[3, 4, 4]
[3, 4, 5]
[3, 5, 4]
[3, 5, 5]
[3, 5, 6]
Those are precisely the triples of values you are after.
Actual code:
// your original conditions
let a = [1, 2, 3]
let b = [3, 4, 5]
let c = [4, 5, 6]
let originals = [a, b, c]
// The actual solution starts here. Note that I never use any hard
// coded numbers.
let n = originals.count
let k = originals[0].count
var indices = [Int]()
for _ in 0..<n {
for i in 0..<k {
indices.append(i)
}
}
let combos = Array(indices.combinations(ofCount: n))
var combosUniq = [[Int]]()
var combosSet = Set<[Int]>()
for combo in combos {
let success = combosSet.insert(combo)
if success.inserted {
combosUniq.append(combo)
}
}
// And here's how to generate your actual desired values.
for combo in combosUniq {
var tuple = [Int]()
for (outerIndex, innerIndex) in combo.enumerated() {
tuple.append(originals[outerIndex][innerIndex])
}
print(tuple) // in real life, do something useful here
}
}
How would I replace values less than 4 with 0 in this array without triggering a SparseEfficiencyWarning and without reducing its sparsity?
from scipy import sparse
x = sparse.csr_matrix(
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[0, 0, 0, 2, 5]])
x[x < 4] = 0
x.toarray() # verifies that this works
Note also that the sparsity between the initial version of x is 11 stored elements, which rises to 15 stored elements after doing the masking.
Manipulate the data array directly
from scipy import sparse
x = sparse.csr_matrix(
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[0, 0, 0, 2, 5]])
x.data[x.data < 4] = 0
>>> x.toarray()
array([[0, 0, 0, 0, 4],
[0, 0, 0, 4, 5],
[0, 0, 0, 0, 5]])
>>> x.data
array([0, 0, 0, 4, 0, 0, 0, 4, 5, 0, 5])
Note that the sparsity is unchanged and there are zero values unless you run x.eliminate_zeros().
x.eliminate_zeros()
>>> x.data
array([4, 4, 5, 5])
If for some reason you don't want to use a boolean mask & fancy indexing in numpy, you can loop over the array with numba:
import numba
#numba.jit(nopython=True)
def _set_array_less_than_to_zero(array, value):
for i in range(len(array)):
if array[i] < value:
array[i] = 0
This should also be faster than the numpy indexing by a fairly substantial degree.
array = np.arange(10)
_set_array_less_than_to_zero(array, 5)
>>> array
array([0, 0, 0, 0, 0, 5, 6, 7, 8, 9])
How do I access the index i and j in a for loop?
mu_1 = [1, 2, 3, 4]
mu_2 = [5, 6, 7, 8]
mu_3 = [9, 10, 11, 12]
mu_4 = [13, 14, 15, 16]
som = 0
for i in range(1, 4):
for j in range(i+1, 5):
r = (mu_i - mu_j)
som = som + r
I want to get this output:
som = ((mu_1 - mu_2) + (mu_1 - mu_3) + (mu_1 - mu_4) +
(mu_2 - mu_3) + (mu_2 - mu_4) +
(mu_3 - mu_4))
I think what you are trying to ask is how to use indices i and j to refer to your mu_n lists. As per the code below, you could add all lists into another list, and index into it.
However, you cannot subtract lists in Python.
Note! : This won't work because the - (subtraction) operation is not supported for list types.
mu = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]]
som = 0
for i in range(4):
for j in range(i+1, 4):
r = (mu[i] - mu[j])
som = som + r
Finally
You might benefit from knowing that indices in Python start from 0.
It is unclear what exactly you are trying to achieve, but you can use the enumerate function to iterate over an iterable together with its indices.
for i, x in enumerate([1, 5, 13, 6]):
# Here, `i` is the items index and `x` the item itself
pass
I followed a tut to help me build a tic tac toe game to keep learning Swift. In doing so I also wanted to add winning slashes for whatever combination that wins.
In my code I have
let winningCombinations = [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]
these are the buttons tags.
I have created labels that are just color bars with no text to be the slashes.
I connected them one as
#IBOutlet weak var lineFirstRow: UILabel!
then hid the label on the storyboard.
I have been trying things like
let lineRowOne = [0, 1, 2]
if lineRowOne = true {
lineFirstRow.isHidden = true
} else {
lineFirstRow.isHidden = false
}
I know this is not correct.
Not entirely sure what you're trying to achieve, but I suspect your solution will be on something like this:
let winningCombinations = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]
let lineOne = [0, 1, 2]
if winningCombinations.contains(where: { $0 == lineOne })
{
// Do Stuff
}
I'm taking Princeton's algorithms-divide-conquer course - 3rd week, and trying to implement the quicksort.
Here's my current implementation with some tests ready to run:
import unittest
def quicksort(x):
if len(x) <= 1:
return x
pivot = x[0]
xLeft, xRight = partition(x)
print(xLeft, xRight)
quicksort(xLeft)
quicksort(xRight)
return x
def partition(x):
j = 0
print('partition', x)
for i in range(0, len(x)):
if x[i] < x[0]:
n = x[j + 1]
x[j + 1] = x[i]
x[i] = n
j += 1
p = x[0]
x[0] = x[j]
x[j] = p
return x[:j + 1], x[j + 1:]
class Test(unittest.TestCase):
def test_partition_pivot_first(self):
arrays = [
[3, 1, 2, 5],
[3, 8, 2, 5, 1, 4, 7, 6],
[10, 100, 3, 4, 2, 101]
]
expected = [
[[2, 1, 3], [5]],
[[1, 2, 3], [5, 8, 4, 7, 6]],
[[2, 3, 4, 10], [100, 101]]
]
for i in range(0, len(arrays)):
xLeft, xRight = partition(arrays[i])
self.assertEqual(xLeft, expected[i][0])
self.assertEqual(xRight, expected[i][1])
def test_quicksort(self):
arrays = [
[1, 2, 3, 4, 5, 6],
[3, 5, 6, 10, 2, 4]
]
expected = [
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 6, 10]
]
for i in range(0, len(arrays)):
arr = arrays[i]
quicksort(arr)
self.assertEqual(arr, expected[i])
if __name__ == "__main__":
unittest.main()
so for array = [3, 5, 6, 10, 2, 4] I get [2, 3, 6, 10, 5, 4] as a result... I can't figure what's wrong with my code. It partitions just fine, but the results are off...
Can anyone chip in? :) Thank you!
it's actually so minor problem that you'd be laughing
the problem resides with quicksort function
the correct one is:
def quicksort(x):
if len(x) <= 1:
return x
pivot = x[0]
xLeft, xRight = partition(x)
print(xLeft, xRight)
quicksort(xLeft)
quicksort(xRight)
x=xLeft+xRight #this one!
return x
what happens is python created a new object out of these xleft and xright they were never an in place-sort
so this is one solution(which is not in place)
the other one is to pass the list,the start_index,end_index
and do it in place
well done fella!
edit:
and actually if you'd print xleft and xright you'd see it performed perfectly:)