Reputation: 1127
I thought that ~ should make 1s into 0s and vice-versa. I used it in my code, yet I'm getting -2s and -1s.
def inverse_graph(graph):
# for each vertex in graph
revg = list(graph)
for i, line in enumerate(revg):
for j, vertex in enumerate(line):
if i != j:
# flip value
graph[i][j] = ~ graph[i][j]
#if vertex == 0:
# graph[i][j] = 1;
#else:
# graph[i][j] = 0;
return revg
def test():
g1 = [[0, 1, 1, 0],
[1, 0, 0, 1],
[1, 0, 0, 1],
[0, 1, 1, 0]]
assert inverse_graph(g1) == [[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0]]
g2 = [[0, 1, 1, 1],
[1, 0, 1, 1],
[1, 1, 0, 1],
[1, 1, 1, 0]]
assert inverse_graph(g2) == [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
.............................................................................................................................................................................................................
Upvotes: 2
Views: 96
Reputation: 41509
Actually, -2 is ~1. Two's complement, remember?
>>> bin(1)
'0b1'
>>> bin(~1)
'-0b10'
The thing is: you're not using bits, but integers. So either you want to revert to using e.g. Booleans (which read less nicely) or you want to use some expression like 0 if x else 1
to flip your elements.
Tip: you can use comprehensions to write this more elegantly:
>>> flipped = lambda graph: [ [0 if x else 1 for x in row] for row in graph]
>>> flipped( [ [1, 0], [0, 1] ] )
[[0, 1], [1, 0]]
Upvotes: 4
Reputation: 91049
While the others are right, an easier way of saying 0 if x else 1
is not x
or maybe int(not x)
.
not x
returns False
if x != 0
and True
otherwise. False
and True
are bool
s, which is a subclass of int
. They can readily be used in a calculation, but for the case you prefer to get proper 0
s and 1
s, or if you need them for indexing a dict
, int(not x)
might be better.
Upvotes: 0
Reputation: 8709
With numpy
it is much easier.
>>> import numpy as np
>>> g1=np.array([[0, 1, 1, 0],
... [1, 0, 0, 1],
... [1, 0, 0, 1],
... [0, 1, 1, 0]])
>>> g2=1-g1
>>> g2
array([[1, 0, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 1]])
~ will work with Boolean datatype:
>>> g1=np.array([[0, 1, 1, 0], # 1 represents True and 0 represents False
... [1, 0, 0, 1],
... [1, 0, 0, 1],
... [0, 1, 1, 0]], dtype=bool)
>>> ~g1
array([[ True, False, False, True],
[False, True, True, False],
[False, True, True, False],
[ True, False, False, True]], dtype=bool)
If you want complement(~)
in 0s and 1s rather than in True False, this will do the trick:
>>> ~g1+0
array([[1, 0, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 0],
[1, 0, 0, 1]])
Upvotes: 2
Reputation: 104712
As xtofl has pointed out, Python's integers use Two's complement representation. This means that the bitwise inverse of 0
is not 1
, but an infinitely long sequence of binary 1
s, which is interpreted as -1
. The inverse of 1
is not 0
, but an infinite number of ones, followed by one zero (which is -2
).
Of course, the number of bits stored for each integer is not infinite. Python will normally use the C integer type long
that your system defines (it is usually 32 or maybe 64 bits long), but operations that would overflow will instead automatically switch to Python's own arbitrary precision long
type if the value is too large to fit (this conversion is handled transparently within the int
type in Python 3).
Anyway, an alternative solution is to use:
graph[i][j] = 1 - graph[i][j]
Or, if you don't mind the values becoming instances of the int
subtype bool
:
graph[i][j] = not graph[i][j]
Python's bool
values are still usable as numbers (False
works just like 0
and True
is just like 1
). The only real difference is that they'll print out with text instead of digits.
Upvotes: 2