Python Modulo Function - python-3.x

I understand that the Modulo function returns the remainder of a division problem.
Ex: 16 % 5 = 3 with a remainder of 1. So 1 would be returned.
>>> 1 % 3 Three goes into 1 zero times remainder 1
1
>>> 2 % 3 Three goes into 2 zero times remainder 2
2
>>> 0 % 3 What happens here? 3 goes into zero, zero times remainder 3
if we follow the logic of the previous two illustrations, that is not what was returned, zero was. Why?
>>> 0 % 3
0

The Python % operator is defined so that x % y == x - (x // y) * y, where x // y = ⌊x / y⌋. For positive integers, this corresponds to the usual notion of the “remainder” of a division. So, for any y ≠ 0,
0 % y
= 0 - ⌊0 / y⌋ * y by definition of %
= 0 - ⌊0⌋ * y because 0 divided by anything is 0
= 0 - 0 * y because 0 is an integer, so floor leaves it unchanged
= 0 - 0 because 0 times anything is 0
= 0

Look at it again:
1 % 3 is 0 remainder 1 => 1 = 3*0 + 1
2 % 3 is 0 remainder 2 => 2 = 3*0 + 2
0 % 3 is 0 remainder 0 [not 3] because 0 = 3*0 + 0
why are you taking what remains after the division in the first two cases but not the last?

Related

How to recognize [1,X,X,X,1] repeating pattern in panda serie

I have a boolean column in a csv file for example:
1 1
2 0
3 0
4 0
5 1
6 1
7 1
8 0
9 0
10 1
11 0
12 0
13 1
14 0
15 1
You can see here 1 is reapting every 5 lines.
I want to recognize this repeating pattern [1,0,0,0] as soon as the repetition is above 10 in python (I have ~20.000 rows/file).
The pattern can start at any position
How could I manage this in python avoiding if .....
# Generate 20000 of 0s and 1s
data = pd.Series(np.random.randint(0, 2, 20000))
# Keep indices of 1s
idx = df[df > 0].index
# Check distance of current index with next index whether is 4 or not,
# Say if position 2 and position 6 is found as 1, so 6 - 2 = 4
found = []
for i, v in enumerate(idx):
if i == len(idx) - 1:
break
next_value = idx[i + 1]
if (next_value - v) == 4:
found.append(v)
print(found)

Replace items in an array with J verb `I.`

Here is a simple replace for a rank-1 list using the I. verb:
y=: _3 _2 _1 1 2 3
0 (I. y<0) } y
The result is
0 0 0 1 2 3
How do I do such a replacement for a rank-2 matrix?
For example,
y2 =: 2 3 $ _3 _2 _1 1 2 3
0 (I. y2<0) } y2
I got (J806)
|index error
| 0 (I.y2<2)}y2
The reason seems to be
(I. y2 < 0)
gives
0 1 2
0 0 0
which isn't taken well by }.
The simplest answer for this problem is to use dyadic >. (Larger of) ...
0 >. y2
0 0 0
1 2 3
If you want to use a more general conditional replacement criteria, then the following form may be useful:
(0 > y2)} y2 ,: 0
0 0 0
1 2 3
If you want it as a verb then you can use the gerund form (v1`v2)} y ↔ (v1 y)} (v2 y) :
(0 > ])`(0 ,:~ ])} y2
0 0 0
1 2 3
If your question is more about scatter index replacement then that is possible too. You need to get the 2D indices of positions you want to replace, for example:
4 $. $. 0 > y2
0 0
0 1
0 2
Now box those indices and use dyadic }:
0 (<"1 (4 $. $. 0 > y2)) } y2
0 0 0
1 2 3
Again you can turn this into a verb using a gerund left argument to dyadic } (x (v0`v1`v2)} y ↔ (x v0 y) (x v1 y)} (x v2 y)) like this:
0 [`([: (<"1) 4 $. [: $. 0 > ])`]} y2
0 0 0
1 2 3
Or
100 101 102 [`([: (<"1) 4 $. [: $. 0 > ])`]} y2
100 101 102
1 2 3
To tidy this up a bit you could define getIdx as separate verb...
getIdx=: 4 $. $.
0 [`([: <"1#getIdx 0 > ])`]} y2
0 0 0
1 2 3
This is not a good solution. My original approach was to change the rank of the test so that it looks at each row separately, but that does not work in the general case (see comments below).
[y2 =: 2 3 $ _3 _2 _1 1 2 3
_3 _2 _1
1 2 3
I. y2<0
0 1 2
0 0 0
0 (I. y2<0)"1 } y2 NB. Rank of 1 applies to each row of y2
0 0 0
1 2 3

how do you replace only a certain number of items in a list randomly?

board = []
for x in range(0,8):
board.append(["0"] * 8)
def print_board(board):
for row in board:
print(" ".join(row))
this code creates a grid of zeros but I wish to replace 5 of them with ones and another five with twos
does anyone know a way to do this?
If you want to randomly set some coordinates with "1" and "2", you can do it like this:
import random
board = []
for x in range(0, 8):
board.append(["0"] * 8)
def print_board(board):
for row in board:
print(" ".join(row))
def generate_coordinates(x, y, k):
coordinates = [(i, j) for i in range(x) for j in range(y)]
random.shuffle(coordinates)
return coordinates[:k]
coo = generate_coordinates(8, 8, 10)
ones = coo[:5]
twos = coo[5:]
for i, j in ones:
board[i][j] = "1"
for i, j in twos:
board[i][j] = "2"
print_board(board)
Output
0 1 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
0 0 2 0 0 0 0 0
1 0 0 0 2 0 0 0
0 0 0 0 2 0 0 2
2 0 0 0 0 0 0 1
Notes:
The code above generates a random sample each time so the output will be different each time (to generate the same use random.seed(42), you can change 42 for any number you want.
The function generate_coordinates receives x (number of rows), y (number of columns) and k (the number of coordinates to pick). It generates a sequence of coordinates of x*y, shuffles it and picks the k first.
In your specific case x = 8, y = 8 and k = 10 (5 for the ones and 5 for the twos)
Finally, this picks the positions for the ones and twos and changes the values:
ones = coo[:5]
twos = coo[5:]
for i, j in ones:
board[i][j] = "1"
for i, j in twos:
board[i][j] = "2"

How to use nested while loops

I'm trying to make a function that uses a nested while loop that prints something like this.
ranges(5,2)
5
0 1 2 3 4
4
0 1 2 3
3
0 1 2
2
0 1
my code that i have so far looks like this
def ranges(high,low):
while high >= low:
print(high)
high = high - 1
y = 0
x = high
while x > y:
print (y, end = " ")
y = y + 1
The output is like this
5
0 1 2 3 4
0 1 2 3
0 1 2
0
I'm pretty sure I missed up in calling the nested while loop because when i split up the code to just print 5,...,2 in a column it works and so does the code for printing the numbers in a row. Any help would be cool
Add print("") right after the while loop, and modify the condition of the while loop to >=:
def ranges(high,low):
while high >= low: # <-- change the condition otherwise you'll miss the last number in every line
print(high)
high = high - 1
y = 0
x = high
while x >= y:
print (y, end = " ")
y = y + 1
print("") # <-- this
ranges(5, 2)
OUTPUT
5
0 1 2 3 4
4
0 1 2 3
3
0 1 2
2
0 1

Combining pairs in a string (Matlab)

I have a string:
sup_pairs = 'BA CE DF EF AE FC GD DA CG EA AB BG'
How can I combine pairs which have the last character of 1 pair is the first character of the follow pairs into strings? And the new strings must contain all of the character 'A','B','C','D','E','F' , 'G', those characters are appeared in the sup_pairs string.
The expected output should be:
S1 = 'BAEFCGD' % because BA will be followed by AE in sup_pairs string, so we combine BAE, and so on...we continue the rule to generate S1
S2 = 'DFCEABG'
If I have AB, BC and BD, the generated strings should be both : ABC and ABD .
If there is any repeated character in the pairs like : AB BC CA CE . We will skip the second A , and we get ABCE .
This, like all good things in life, is a graph problem. Each letter is a node, and each pair is an edge.
First we must transform your string of pairs into a numeric format so we can use the letters as subscripts. I will use A=2, B=3, ..., G=8:
sup_pairs = 'BA CE DF EF AE FC GD DA CG EA AB BG';
p=strsplit(sup_pairs,' ');
m=cell2mat(p(:));
m=m-'?';
A=sparse(m(:,1),m(:,2),1);
The sparse matrix A is now the adjacency matrix (actually, more like an adjacency list) representing our pairs. If you look at the full matrix of A, it looks like this:
>> full(A)
ans =
0 0 0 0 0 0 0 0
0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 1
0 0 0 0 0 1 0 1
0 1 0 0 0 0 1 0
0 1 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
As you can see, the edge BA, which translates to subscript (3,2) is equal to 1.
Now you can use your favorite implementation of Depth-first Search (DFS) to perform a traversal of the graph from your starting node of choice. Each path from the root to a leaf node represents a valid string. You then transform the path back into your letter sequence:
treepath=[3,2,6,7,4,8,5];
S1=char(treepath+'?');
Output:
S1 = BAEFCGD
Here's a recursive implementation of DFS to get you going. Normally in MATLAB you have to worry about not hitting the default limitation on recursion depth, but you're finding Hamiltonian paths here, which is NP-complete. If you ever get anywhere near the recursion limit, the computation time will be so huge that increasing the depth will be the least of your worries.
function full_paths = dft_all(A, current_path)
% A - adjacency matrix of graph
% current_path - initially just the start node (root)
% full_paths - cell array containing all paths from initial root to a leaf
n = size(A, 1); % number of nodes in graph
full_paths = cell(1,0); % return cell array
unvisited_mask = ones(1, n);
unvisited_mask(current_path) = 0; % mask off already visited nodes (path)
% multiply mask by array of nodes accessible from last node in path
unvisited_nodes = find(A(current_path(end), :) .* unvisited_mask);
% add restriction on length of paths to keep (numel == n)
if isempty(unvisited_nodes) && (numel(current_path) == n)
full_paths = {current_path}; % we've found a leaf node
return;
end
% otherwise, still more nodes to search
for node = unvisited_nodes
new_path = dft_all(A, [current_path node]); % add new node and search
if ~isempty(new_path) % if this produces a new path...
full_paths = {full_paths{1,:}, new_path{1,:}}; % add it to output
end
end
end
This is a normal Depth-first traversal except for the added condition on the length of the path in line 15:
if isempty(unvisited_nodes) && (numel(current_path) == n)
The first half of the if condition, isempty(unvisited_nodes) is standard. If you only use this part of the condition you'll get all paths from the start node to a leaf, regardless of path length. (Hence the cell array output.) The second half, (numel(current_path) == n) enforces the length of the path.
I took a shortcut here because n is the number of nodes in the adjacency matrix, which in the sample case is 8 rather than 7, the number of characters in your alphabet. But there are no edges into or out of node 1 because I was apparently planning on using a trick that I never got around to telling you about. Rather than run DFS starting from each of the nodes to get all of the paths, you can make a dummy node (in this case node 1) and create an edge from it to all of the other real nodes. Then you just call DFS once on node 1 and you get all the paths. Here's the updated adjacency matrix:
A =
0 1 1 1 1 1 1 1
0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 1
0 0 0 0 0 1 0 1
0 1 0 0 0 0 1 0
0 1 0 0 0 0 1 0
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0
If you don't want to use this trick, you can change the condition to n-1, or change the adjacency matrix not to include node 1. Note that if you do leave node 1 in, you need to remove it from the resulting paths.
Here's the output of the function using the updated matrix:
>> dft_all(A, 1)
ans =
{
[1,1] =
1 2 3 8 5 7 4 6
[1,2] =
1 3 2 6 7 4 8 5
[1,3] =
1 3 8 5 2 6 7 4
[1,4] =
1 3 8 5 7 4 6 2
[1,5] =
1 4 6 2 3 8 5 7
[1,6] =
1 5 7 4 6 2 3 8
[1,7] =
1 6 2 3 8 5 7 4
[1,8] =
1 6 7 4 8 5 2 3
[1,9] =
1 7 4 6 2 3 8 5
[1,10] =
1 8 5 7 4 6 2 3
}

Resources