python cyclic shifting of the characters in the string - python

Subclass sstr of the standard str type that implements the "<<" and ">>" methods as a cyclic shifting of the characters in the string.What trying to do is
>>> s1 = sstr("abcde")
>>> s1 << 0
'abcde'
>>> s1 >> 0
'abcde'
>>> s1 << 2
'cdeab'
>>> s1 >> 2
'deabc'
>>> s1 >> 5
'abcde'
# my attempt:
import string
class sstr(str):
def __new__(self, other):
return str.__new__(self, other.upper())
def __ilshift__(self, other):
return str.__ilshift(other)
def __rshift__(self, other):
return str.__rshift(other)

This smells like homework, so I'm not going to post actual code here. But to help, I will point out flaws I see in your code and an algorithm:
My python 2.7.2 reports no __ilshift or __irshift in str. Also, if you are trying to shift a string by a certain number of characters, then you shouldn't be shifting the variable you call other. You should be shifting self by other many characters. That being said, you're probably better off naming other as n or some such.
Now, I assume you know how circular shifting is supposed to work. The examples you provide get the message across well.
As a simple algorithm (easy to read/understand), try this (pseudo-code follows):
function __ilshift(self, n) { // self is the string to be shifted. n denotes how many characters to shift it by
answer = copy()
for i = 1 to n {
answer = self[1:] //answer = everything in self excluding the first character
answer += self[0] // append the first character of self to answer
}
return answer
}
The above solution would work. Though, it is quite inefficient. We know that when an n-character string is shifted by n, the result of the shifting is the string itself. When you think about this a little more, you realize that you end up shifting by n % lengthOfSelf. Thus, the for i = 1 to n turns into for i = 1 to n%len(self).
Still, we can make this more efficient. To do this would require splicing self at the appropriate index, which I'll let you figure out, because I think this is homework.
Hope this gets you closer!

s1 << 0
This calls __lshift__, not __ilshift__. The i stands for in-place; you can't change a string in-place anyway, and aren't trying to here (you're trying to create a new value).
The problem with your actual code is that you're trying to implement the shift by just calling the base str class's shift. But the base str class doesn't have that shift operation - that's the entire reason you have this exercise!
Hint: put together two slices of the string. 'foobar' << 2 is 'obar' + 'fo'. Can you see how to slice the string to get those? How do the numbers you use for the slices relate to the number specified for shifting?

Related

Comparing bit representation of objects in Python

I am watching a video named The Mighty Dictionary which has the following code:
k1 = bits(hash('Monty'))
k2 = bits(hash('Money'))
diff = ('^' [a==b] for a,b in zip(k1,k2))
print(k1,k2,''.join(diff))
As I understand, bits is not a built-in method in Python, but his own written method which is similar to `format(x, 'b'), or is it something that existed in Python 2? (I've never wrote code in Python 2)
I've tried to accomplish the same, get the bits representation of the strings and check where the bits differ:
k1 = format(hash('Monty'),'b')
k2 = format(hash('Money'),'b')
diff = ('^ ' [a==b] for a,b in zip(k1,k2))
print(k1,'\n',k2,'\n',''.join(diff))
I do get the expected result:
UPDATED
Had to shift the first line by 1 space to match the symbols
110111010100001110100101100000100110111111110001001101111000110
-1000001111101001011101001010101101000111001011011000011110100
^ ^^^ ^ ^^ ^^^ ^^^^^^^ ^ ^^^^^ ^^ ^^ ^^^^^^^ ^ ^ ^^^
Also, the lengths of the bits are not the same, whereas I understand that no matter the string, it will take the same, in my case, 64 bits? But its 63 and 62.
print(len(format(hash('Monty'),'b')))
print(len(format(hash('Money'),'b')))
63
62
So, to sum up my question:
Is bits a built-in method in Python2?
Is the recommended way to compare bit representation of an object is using the following:
def fn():
pass
print(format(hash(fn),'b'))
# -111111111111111111111111111111111101111000110001011100000000101
Shouldn't all objects have the same length of bits that represent the object depending on the processor? If I run the following code several times I get these results:
def fn():
pass
def nf():
pass
print(format(hash(fn),'b'))
print(format(hash(nf),'b'))
# first time
# 10001001010011010111110000100
# -111111111111111111111111111111111101110110101100101000001000001
# second time
# 10001001010011010111111101010
# 10001001010011010111110000100
# third time
# 10001001010011010111101010001
# -111111111111111111111111111111111101110110101100101000001000001
No, bits is not a built-in function in Python 2 or Python 3.
By default format() doesn't show leading zeroes. Use the format string 032b to format the number in a 32-character field with leading zeroes.
>>> format(hash('Monty'), '032b')
'1001000100011010010110101101101011000010101011100110001010001'
Another problem you're running into is that hash() can return negative numbers. Maybe this couldn't happen in Python 2, or his bits() function shows the two's complement bits of the number. You can do this by normalizing the input:
def bits(n):
if n < 0:
n = 2**32 + n
return format(n, '032b')
Every time you run the code, you define new fn and nf functions. Different functions will not necessarily have the same hash code, even if they have the same name.
If you don't redefine the functions, you should get the same hash codes each time.
Hashing strings and numbers just depends on the contents, but hashing more complex objects depends on the specific instance.

Code notes: Explaining the what is happening in the code [duplicate]

This question already has answers here:
What does Python's eval() do?
(12 answers)
Closed 4 years ago.
I am a newbie developer. I have used the code below but I would like to understand how the last line works, can someone please explain to me the last line return eval(((str(a)+"*")*b)[:-1]) of the code?
def power(a,b):
if b == 0:
return 1
else:
return eval(((str(a)+"*")*b)[:-1])
eval evaluates python code or lets Python program run Python code within itself.
example:
CODE:
a = 15
eval('print(a + 3)')
OUTPUT:
18
when you return the following
eval(((str(a)+"*")*b)[:-1])
what you basically doing is this( for example if you are computing power(2,5)):
str(a) -> changes the value of a to string. in this case "2"
str(a)+"*" -> concatinate the above string to the multiplication sign. now we have "2*"
(str(a)+"*")*b) -> duplicates the above string b times. That is "2*"+"2*"+"2*"+"2*"+"2*", that is five times and now you have "2*2*2*2*2*"
But as you can see there is an extra "*" at the end. To remove this one we use [:-1]. what this basically doing is select all except the last one. ":" basically means all.
so the final expression to be evaluated is "2*2*2*2*2". which is 2^5.
The best way is to use a**b for computing power. However, if you want to use eval then consider joining the string in this way: eval('*'.join(str(a)*b)). In this, str(a) will convert integer a to string a then *b will repeat the a b times and finally the '*'.join() will join all the a's together with * in between and create a string something like a*a*a*a. eval will then evaluate the string as if it is an expression.
return eval(((str(a)+"*")*b)[:-1])
is equivalent to
a_str=str(a) # convert a in STRING
a_star=a_str+"*" # concat the string a_str with "*"
a_repeted=a_star*b # repeat a_star "b" times
exp=(a_repeted)[:-1] # get all a_repeted car except the last on (ex 3*3*3*3 for a=3 and b=4)
res=eval(exp) # evalutate the expression
return res
it'is equivalent to (really better ;-) !) :
def power(a,b):
return a ** b
A terrible idea, as others have said - if you're a newbie, consider finding a better guide!
eval reads a string and evaluates it as if it were not (as if it is not in quotes). So we construct a string of a ** b (ie a^b), and ask Python to read it, then return all but the last character. Pretty pointless but there you go.
eval() is never a good idea to use. Read about its dangerous behaviour here.
You just need ** operator which is equivalent to ^ (raise to) operator you see in other languages:
def power(a,b):
return a ** b

How to convert hex to signed long long with python?

I have a hex string f6befc34e3de2d30. I want to convert it to signed long long, but
x['id'], = struct.unpack('>q', 'f6befc34e3de2d30'.decode('hex'))
gives:
-0b100101000001000000111100101100011100001000011101001011010000
0b1111011010111110111111000011010011100011110111100010110100110000
expected.
Thanks!
You could do long('f6befc34e3de2d30', 16)
bin(long('f6befc34e3de2d30', 16))
>>> '0b1111011010111110111111000011010011100011110111100010110100110000'
Edit: Follow up on #Paul Panzer's comment. That would be true with C type long implementation based on ALU hardware. You could not have signed integer larger that 2^63. However, Python's implementation is different, and relies on array representation of big numbers, and Karatsuba algorithm for arithmetic operations. That is why this method works.
Edit 2: Following OPs questions. There is no question of "first bit as sign". In your question you explicitly want to use the long construct of Python, for which the implementation is not the one you expect in the sense that, the representation it uses isn't the same as what you may be familiar with in C. Instead it represents large integers as an array. So if you want to implement some kind of first bit logic, you have to do it yourself. I have no culture or experience in that whatsoever so the following may come completely wrong as someone knowking his stuff, but still let me give you my take on this.
I see two ways of proceeding. In the first one you agree on a convention for the max long you want to work with, and then implement the same kind of logic the ALU does. Let us say for the sake of argument we want to work with sign long in the range [-2^127, 2^127-1]. We can do the following
MAX_LONG = long('1' + "".join([str(0)]*127), 2)
def parse_nb(s):
# returns the first bit and the significand in the case of a usual
# integer representation
b = bin(long(s, 16))
if len(b) < 130: # deal with the case where the leading zeros are absent
return "0", b[2:]
else:
return b[2], b[3:]
def read_long(s):
# takes an hexadecimal representation of a string, and return
# the corresponding long with the convention stated above
sign, mant = parse_nb(s)
b = "0b" + mant
if sign == "0":
return long(b, 2)
else:
return -MAX_LONG + long(b, 2)
read_long('5')
>>> 5L
# fffffffffffffffffffffffffffffffb is the representation of -5 using the
# usual integer representation, extended to 128 bits integers
read_long("fffffffffffffffffffffffffffffffb")
>>> -5L
For the second approach, you don't consider that there a MAX_LONG, but that the first bit is always the sign bit. Then you would have to modify the parse_nb method above. I leave that as an exercise :).

Finding the length of first half of a string using string slicing in Python?

I'm working on an assignment in PyCharm, and have been tasked with the following problem:
The len() function is used to count how many characters a string contains. Get the first half of the string storied in the variable 'phrase'.
Note: Remember about type conversion.
Here's my code so far that it's given me:
phrase = """
It is a really long string
triple-quoted strings are used
to define multi-line strings
"""
first_half = len(phrase)
print(first_half)
I have no idea what to do. I need to use string slicing to find the first half of the string "phrase". Any help appreciated. I apologize for my ignorance.
Just slice the first half of the string, be sure to use // in the event that the string is of odd length like:
print phrase[:len(phrase) // 2] # notice the whitespace in your literal triple quote
Try something like:
first_half = len(phrase)
print(phrase[0:first_half/2])
It will need to be smarter to handle strings of odd length. See this question for more on slicing.
first_half = phrase[:len(phrase)//2] or phrase[:int(len(phrase)/2)]
Note: Remember about type conversion.
In Python 2 the division will yield an int, however in Python 3 you want to use an int division like this half = len(phrase) // 2
Below is a Python 2 version
>>> half = len(phrase) / 2
>>> phrase[:half]
'\nIt is a really long string\ntriple-quoted st'
No need for the 0 in phrase[0:half], phrase[:half] looks better :)
Try this print(string[:int(len(string)/2)])
len(string)/2 returns a decimal normally so that's why I used int()
Use slicing and bit shifting (which will be faster should you have to do this many times):
>>> s = "This is a string with an arbitrary length"
>>> half = len(s) >> 1
>>> s[:half]
'This is a string wit'
>>> s[half:]
'h an arbitrary length'
Try this:
phrase = """
It is a really long string
triple-quoted strings are used
to define multi-line strings
"""
first_half = phrase[0: len(phrase) // 2]
print(first_half)
you can simply slicing a string using it's indexes.
For Example:
def first_half(str):
return str[:len(str)/2]
The above function first_half accept a string and return it's half using slicing

Slick way to reverse the (binary) digits of a number in Python?

I am looking for a slick function that reverses the digits of the binary representation of a number.
If f were such a function I would have
int(reversed(s),2) == f(int(s,2)) whenever s is a string of zeros and ones starting with 1.
Right now I am using lambda x: int(''.join(reversed(bin(x)[2:])),2)
which is ok as far as conciseness is concerned, but it seems like a pretty roundabout way of doing this.
I was wondering if there was a nicer (perhaps faster) way with bitwise operators and what not.
How about
int('{0:b}'.format(n)[::-1], 2)
or
int(bin(n)[:1:-1], 2)
The second method seems to be the faster of the two, however both are much faster than your current method:
import timeit
print timeit.timeit("int('{0:b}'.format(n)[::-1], 2)", 'n = 123456')
print timeit.timeit("int(bin(n)[:1:-1], 2)", 'n = 123456')
print timeit.timeit("int(''.join(reversed(bin(n)[2:])),2)", 'n = 123456')
1.13251614571
0.710681915283
2.23476600647
You could do it with shift operators like this:
def revbits(x):
rev = 0
while x:
rev <<= 1
rev += x & 1
x >>= 1
return rev
It doesn't seem any faster than your method, though (in fact, slightly slower for me).
Here is my suggestion:
In [83]: int(''.join(bin(x)[:1:-1]), 2)
Out[83]: 9987
Same method, slightly simplified.
I would argue your current method is perfectly fine, but you can lose the list() call, as str.join() will accept any iterable:
def binary_reverse(num):
return int(''.join(reversed(bin(num)[2:])), 2)
It would also advise against using lambda for anything but the simplest of functions, where it will only be used once, and makes surrounding code clearer by being inlined.
The reason I feel this is fine as it describes what you want to do - take the binary representation of a number, reverse it, then get a number again. That makes this code very readable, and that should be a priority.
There is an entire half chapter of Hacker's Delight devoted to this issue (Section 7-1: Reversing Bits and Bytes) using binary operations, bit shifts, and other goodies. Seems like these are all possible in Python and it should be much quicker than the binary-to-string-and-reverse methods.
The book isn't available publicly but I found this blog post that discusses some of it. The method shown in the blog post follows the following quote from the book:
Bit reversal can be done quite efficiently by interchanging adjacent
single bits, then interchanging adjacent 2-bit fields, and so on, as
shown below. These five assignment statements can be executed in any
order.
http://blog.sacaluta.com/2011/02/hackers-delight-reversing-bits.html
>>> def bit_rev(n):
... return int(bin(n)[:1:-1], 2)
...
>>> bit_rev(2)
1
>>>bit_rev(10)
5
What if you wanted to reverse the binary value based on a specific amount of bits, i.e. 1 = 2b'00000001? In this case the reverse value would be 2b'10000000 or 128 (dec) respectively 0x80 (hex).
def binary_reverse(num, bit_length):
# Convert to binary and pad with 0s on the left
bin_val = bin(num)[2:].zfill(bit_length)
return int(''.join(reversed(bin_val)), 2)
# Or, alternatively:
# return int(bin_val[::-1], 2)

Categories

Resources