Generating all unique orders of looping series of characters (all circular permutations) - permutation

I have a string that is made out of Xs and Ys.
For the sake of the question let's say this string is constructed of Four-Xs and Two-Ys:
XXYYYY
How can I generate all of the possible unique strings that are made out of Four-Xs and Two-Ys given that the string is not considered unique if by looping (/rotating/shifting) its characters around it produces a string that was already found?
For instance:
XXYYYY is considered similar to YXXYYY and YYYXXY (cardinal numbers added clarify)
123456 612345 456123
Notice: that the order of the characters stays unchanged, the only thing that changed is the starting character (The original string starts with 1, the 2nd string with 6, and the 3rd with 4, but they all keep the order).
In the case of Two-Xs and Four-Ys (our example) all the possible permutations that are unique are:
XXYYYY
XYXYYY
XYYXYY
And every other order would be a shifted version of one of those 3.
How would you generate all of the possible permutation of a string with and N number of Xs and an M number of Ys?

Essentially you need to generate combinatorial objects named binary necklaces with fixed number of ones
This is Python code adapted from Sawada article "A fast algorithm to generate necklaces with fixed contents".
(I used the simplest variant, there are also more optimized ones)
n = 6
d = 3
aa = [0] * n
bb = [n - d, d] #n-d zeros, d ones
def SimpleFix(t, p):
if t > n:
if n % p == 0:
print(aa)
else:
for j in range(aa[t - p - 1], 2):
if bb[j] > 0:
aa[t - 1] = j
bb[j] -= 1
if j == aa[t-p-1]:
SimpleFix(t+1, p)
else:
SimpleFix(t+1, t)
bb[j] += 1
SimpleFix(1, 1)
#example for 3+3
[0, 0, 0, 1, 1, 1]
[0, 0, 1, 0, 1, 1]
[0, 0, 1, 1, 0, 1]
[0, 1, 0, 1, 0, 1]

Related

Rearrange an array A so that A wins maximum number of comparisons with array B when comparison is done one-on-one

Let's say I have an array A = [3, 6, 7, 5, 3, 5, 6, 2, 9, 1] and B = [2, 7, 0, 9, 3, 6, 0, 6, 2, 6]
Rearrange elements of array A so that when we do comparison element-wise like 3 with 2 and 6 with 7 and so on, we have maximum wins (combinations where A[i] > B[i] are maximum (0<=i<len(A))).
I tried below approach:
def optimal_reorder(A,B,N):
tagged_A = [('d',i) for i in A]
tagged_B = [('a',i) for i in B]
merged = tagged_A + tagged_B
merged = sorted(merged,key=lambda x: x[1])
max_wins = 0
for i in range(len(merged)-1):
print (i)
if set((merged[i][0],merged[i+1][0])) == {'a','d'}:
if (merged[i][0] == 'a') and (merged[i+1][0] == 'd'):
if (merged[i][1] < merged[i+1][1]):
print (merged[i][1],merged[i+1][1])
max_wins += 1
return max_wins
as referenced from
here
but this approach doesn't seem to give correct answer for given A and B i,e if A = [3, 6, 7, 5, 3, 5, 6, 2, 9, 1] and B = [2, 7, 0, 9, 3, 6, 0, 6, 2, 6] then maximum wins is 7 but my algorithm is giving 5.
is there something I am missing here.
revised solution as suggested by #chqrlie
def optimal_reorder2(A,B):
arrA = A.copy()
C = [None] * len(B)
for i in range(len(B)):
k = i + 1
all_ele = []
while (k < len(arrA)):
if arrA[k] > B[i]:
all_ele.append(arrA[k])
k += 1
if all_ele:
e = min(all_ele)
else:
e = min(arrA)
C[i] = e
arrA.remove(e)
return C
How about this algorithm:
start with an empty array C.
for each index i in range(len(B)).
if at least one of the remaining elements of A is larger than B[i], choose e as the smallest of these elements, otherwise choose e as the smallest element of A.
set C[i] = e and remove e from A.
C should be a reordering of A that maximises the number of true comparisons C[i] > B[i].
There’s probably a much better algorithm than this, but you can think of this as a maximum bipartite matching problem. Think of the arrays as the two groups of nodes in the bipartite graph, then add an edge from A[i] to B[j] if A[i] > B[j]. Then any matching tells you how to pair elements of A with elements of B such that the A element “wins” against the B element, and a maximum matching tells you how to do this to maximize the number of wins.
I’m sure there’s a better way to do this, and I’m excited to see what other folks come up with. But this at least shows you can solve this in polynomial time.

Divide binary row and convert each part to float or decimal python 3

I am using python-3.x and I am trying to take each binary row in the [x] array and divided into two parts the first four digits will make the first number and the second four digits as the secund number after I convert them to floats.
there is a function "def test(binary)" that will do the convert from binary to floats, and there are two loops to go over the array.
for example, the first row is: [1, 0, 0, 1, 1, 0, 0, 0]
I want to divide it to 1001 - 1000
then the final result will be [9, 8]
import numpy as np
n = 4
##################################
# convert a list of Binary's to decimal
def test(binary):
wordlength = binary.shape[1]
shift = np.arange(wordlength-1, -1, -1)
decimal = np.sum(binary << shift, 1)
print (decimal)
##################################
np.set_printoptions(threshold=np.nan)
x = np.array([[1, 0, 0, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0],
[1, 0, 0, 1, 1, 1, 0, 1]])
print(x)
for ii in range (3) :
start_array = 0
X = x[ii]
print ("X:" '\n', X)
#print(ii, X)
for i in range (2) :
end_array= start_array + n
print ("end_array:" '\n', end_array)
print ("start_array:" '\n', start_array)
flot = np.zeros ((3, 2))
flot[ii, i] = test(x[start_array:end_array])
print (flot)
start_array=end_array
but i couldn't get the right result I am not sure where is the problem, if my way to solve this problem is right
Given a list of integers you could do this:
Convert to a list of strings
Concatenate using join
Split the list in half
Use int to convert to binary
In long form:
x = [1,0,0,1,1,0,0,0]
# The following two lines are equivalent - choose the most readable
strings = ''.join(map(str,x)) # Using map
strings = ''.join(str(z) for z in x) # Using a list loop
print(strings)
strings1 = strings[:4] # First four
strings2 = strings[-4:] # Last four
bin1 = int(strings1)
bin2 = int(strings2)
# int function takes a second argument for base
int1 = int(strings1,2)
int2 = int(strings2,2)
In one line:
int1 = int(''.join(map(str,x))[:4],2)
int2 = int(''.join(map(str,x))[-4:],2)
Fitting your question, which contains a list of lists:
# For each element l of list x (l being a list)
for l in x:
for z in l:
int1 = int(''.join(map(str,z))[:4],2)
int2 = int(''.join(map(str,z))[-4:],2)
print(int1)
print(int2)

Algorithm to fill an array randomly without collision

Say I have an array of N integers set to the value '0', and I want to pick a random element of that array that has the value '0' and put it to value '1'
How do I do this efficiently ?
I came up with 2 solutions but they look quite ineficient
First solution
int array[N] //init to 0s
int n //number of 1s we want to add to the array
int i = 0
while i < n
int a = random(0, N)
if array[a] == 0
array[a] = 1
i++
end if
end while
It would be extremely inefficient for large arrays because of the probability of collision
The second involves a list containing all the 0 positions remaining and we choose a random number between 0 and the number of 0 remaining to lookup the value in the list that correspond to the index in the array.
It's a lot more reliable than the first solution, since the number of operations is bounded, but still has a worst case scenario complexity of N² if we want to fill the array completely
Your second solution is actually a good start. I assume that it involves rebuilding the list of positions after every change, which makes it O(N²) if you want to fill the whole array. However, you don't need to rebuild the list every time. Since you want to fill the array anyway, you can just use a random order and choose the remaining positions accordingly.
As an example, take the following array (size 7 and not initially full of zeroes) : [0, 0, 1, 0, 1, 1, 0]
Once you have built the list of zeros positions, here [0, 1, 3, 6], just shuffle it to get a random ordering. Then fill in the array in the order given by the positions.
For example, if the shuffle gives [3, 1, 6, 0], then you can fill the array like so :
[0, 0, 1, 0, 1, 1, 0] <- initial configuration
[0, 0, 1, 1, 1, 1, 0] <- First, position 3
[0, 1, 1, 1, 1, 1, 0] <- Second, position 1
[0, 1, 1, 1, 1, 1, 1] <- etc.
[1, 1, 1, 1, 1, 1, 1]
If the array is initially filled with zeros, then it's even easier. Your initial list is the list of integers from 0 to N (size of the array). Shuffle it and apply the same process.
If you do not want to fill the whole array, you still need to build the whole list, but you can truncate it after shuffling it (which just means to stop filling the array after some point).
Of course, this solution requires that the array does not change between each step.
You can fill array with n ones and N-n zeros and make random shuffling.
Fisher-Yates shuffle has linear complexity:
for i from N−1 downto 1 do
j ← random integer such that 0 ≤ j ≤ i
exchange a[j] and a[i]

Numpy: finding nonzero values along arbitrary dimension

It seems I just cannot solve this in Numpy: I have a matrix, with an arbitrary number of dimensions, ordered in an arbitrary way. Inside this matrix, there is always one dimension I am interested in (as I said, the position of this dimension is not always the same). Now, I want to find the first nonzero value along this dimension. In fact, I need the index of that value to perform some operations on the value itself.
An example: if my matrix a is n x m x p and the dimension I am interested in is number 1, I would do something like:
for ii in xrange(a.shape[0]):
for kk in xrange(a.shape[2]):
myview = np.squeeze(a[ii, :, kk])
firsti = np.nonzero(myview)[0][0]
myview[firsti] = dostuff
Apart from performance considerations, I really do not know how to do this having different number of dimensions, and having the dimension I am interested in an arbitrary position.
You can abuse np.argmax for your purpose. Here, you can specify the axis which you are interested in, where 0 is along columns, 1 is along rows, and so on. You just need an array which contains the same value for all elements that are not zero. You can achieve that by doing a != 0, as this will contain False (meaning 0) for all zero-elements and True (meaning 1) for all non-zero-elements. Now np.argmax(a != 0, axis=1) would give you the first non-zero element along the 1 axis.
For example:
import numpy as np
a = np.array([[0, 1, 4],[1, 0, 2],[0, 0, 1]])
# a = [[0, 1, 4],
# [1, 0, 2],
# [0, 0, 1]]
print(np.argmax(a!=0, axis=0))
# >>> array([1, 0, 0]) -> along columns
print(np.argmax(a!=0, axis=1))
# >>> array([1, 0, 2]) -> along rows
This will also work for higher dimension, but the output is less instructive, as it is hard to imagine.

Longest common substring of 2 strings implementation

I'm trying to implement the longest common substring algorithm in C, and after reading the post below, i'm really confused about the following part:
Now, the greatest value is LCP[2]=3, but it is for SA[1] and SA[2], both of which start in the string A. So, we ignore that. On the other hand, LCP[4]=2 is for SA[3] (corresponds to the suffix bc of B) and SA[4] (corresponding to suffix bcabc#bc of A). So, this is the longest common substring.
My LCP result is also different from the post example.
https://cs.stackexchange.com/questions/9555/computing-the-longest-common-substring-of-two-strings-using-suffix-arrays
string A = abcabc
string B = bc
string separator: '#'
Suffix array
[#bc, abc#bc, abcabc#bc, bc, bc#bc, bcabc#bc, c, c#bc, cabc#bc]
LCP
[-1, 0, 3, 0, 2, 2, 0, 1, 1]
OR removing the first element
Suffix array
[abc#bc, abcabc#bc, bc, bc#bc, bcabc#bc, c, c#bc, cabc#bc]
LCP
[0, 3, 0, 2, 2, 0, 1, 1]
I see that SA[3] corresponds to bc, but SA[4] corresponds (i guess) to #bcbc. So, that's what confuses me.
Anyone can clarify on this? Thanks!
I see that SA[3] corresponds to bc, but SA[4] corresponds (i guess) to #bcbc.
There is no #bcbc to be found anywhere above. The quote says "SA[4] (corresponding to suffix bcabc#bc of A)" and that's certainly true:
0 1 2 3 4 5 6 7 index
[abc#bc, abcabc#bc, bc, bc#bc, bcabc#bc, c, c#bc, cabc#bc] Suffix Array
[0, 3, 0, 2, 2, 0, 1, 1] LCP
SA[2] is a suffix of B and SA[3] is a suffix of A(#B), so the longest common substring is bc, of length 2.

Resources