Python3 write string as binary - python-3.x

For a Python 3 programming assignment I have to work with Huffman coding. It's simple enough to generate the correct codes which result in a long string of 0's and 1's.
Now my problem is actually writings this string of as binary and not as text. I attempted to do this:
result = "01010101 ... " #really long string of 0's and 1's
filewrt = open(output_file, "wb") #appending b to w should write as binary, should it not?
filewrt.write(result)
filewrt.close()
however I'm still geting a large text file of 0 and 1 characters. How do I fix this?
EDIT: It seems as if I just simply don't understand how to represent an arbitrary bit in Python 3.
Based on this SO question I devised this ugly monstrosity:
for char in result:
filewrt.write( bytes(int(char, 2)) )
Instead of getting anywhere close to working, it outputted a zero'd file that was twice as large as my input file. Can someone please explain to me how to represent binary arbitrarily? And in the context of creating a huffman tree, how do I go about concatinating or joining bits based on their leaf locations if I should not use a string to do so.

def intToTextBytes(n, stLen=0):
bs = b''
while n>0:
bs = bytes([n & 0xff]) + bs
n >>= 8
return bs.rjust(stLen, b'\x00')
num = 0b01010101111111111111110000000000000011111111111111
bs = intToTextBytes(num)
print(bs)
open(output_file, "wb").write(bs)
EDIT: A more complicated, but faster (about 3 times) way:
from math import log, ceil
intToTextBytes = lambda n, stLen=0: bytes([
(n >> (i<<3)) & 0xff for i in range(int(ceil(log(n, 256)))-1, -1, -1)
]).rjust(stLen, b'\x00')

Related

How to multiply numbers of a string by its position in the string

I am a newby on this. I am trying to multiply every single element of the string below ('10010010') by 2 to the power of the position of the element in the string and sum all the multiplications. So far I am trying to do it like this, but I cannot achieve to figure out how to do it.
def decodingvalue(str1):
# read each character in input string
for ch in str1:
q=sum(2^(ch-1)*ch.isdigit())
return q
Function call
print(decodingvalue('10010010'))
Thanks a lot for your help!
I think you trying convert binary to int. If that so you can do the following:
str = '101110101'
#length is counted 1 to n, decrementing by 1 changes to 0-(n-1)
c = len(str)-1
q = 0
for ch in str:
print(q,c,ch)
q = q + (int(ch)*(2**c)) #in python power is '**'
c = c-1
if c == -1:
break
print(q)
you can of course optimize it and finish in fewer lines.
In python ^ (caret operator) is a Bitwise XOR.

Stuck on Cryptopals Crypto Challenge 3 set 1

I'm failry new to cryptography and programming as a whole ( mabey a few months) and i started the cryptopal challenges. I got the first 2 done correctly with alot of reading into how to convert things in python.
I'm getting stuck on the code for the 3rd one, "Single-Byte XOR" where they give you a hex string and tell you to write a program to find the key they used to XOR the string.
I am aware of how i would go about doing this (without looking solutions):
1) convert the string to binary
2) loop through all character values XORing them individually with the given ciphertext
3) checking these XORd results to see which one looks "the most english"
I guess im just confused on the way bytes behave in python.
here is my code:
my_ciphertext = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
binary_rep_of_ciphertext = binascii.unhexlify(my_ciphertext)
array_of_ciphertext = bytearray(binary_rep_of_ciphertext)
def xor_string_and_char(my_char_value):
result = array_of_ciphertext ^ my_char_value
return '{:x}'.format(result) # convert back to hexadecimal
x = 0
assert x==0
while x in range(255):
my_plaintext = xor_string_and_char(x)
print('b' + my_plaintext)
x=x+1

Generate an integer for encryption from a string and vice versa

I am trying to write an RSA code in python3. I need to turn user input strings (containing any characters, not only numbers) into integers to then encrypt them. What is the best way to turn a sting into an integer in Python 3.6 without 3-rd party modules?
how to encode a string to an integer is far from unique... there are many ways! this is one of them:
strg = 'user input'
i = int.from_bytes(strg.encode('utf-8'), byteorder='big')
the conversion in the other direction then is:
s = int.to_bytes(i, length=len(strg), byteorder='big').decode('utf-8')
and yes, you need to know the length of the resulting string before converting back. if length is too large, the string will be padded with chr(0) from the left (with byteorder='big'); if length is too small, int.to_bytes will raise an OverflowError: int too big to convert.
The #hiro protagonist's answer requires to know the length of the string. So I tried to find another solution and good answers here: Python3 convert Unicode String to int representation. I just summary here my favourite solutions:
def str2num(string):
return int(binascii.hexlify(string.encode("utf-8")), 16)
def num2str(number):
return binascii.unhexlify(format(number, "x").encode("utf-8")).decode("utf-8")
def numfy(s, max_code=0x110000):
# 0x110000 is max value of unicode character
number = 0
for e in [ord(c) for c in s]:
number = (number * max_code) + e
return number
def denumfy(number, max_code=0x110000):
l = []
while number != 0:
l.append(chr(number % max_code))
number = number // max_code
return ''.join(reversed(l))
Intersting: testing some cases shows me that
str2num(s) = numfy(s, max_code=256) if ord(s[i]) < 128
and
str2num(s) = int.from_bytes(s.encode('utf-8'), byteorder='big') (#hiro protagonist's answer)

Finding the additive and multiplicative roots of a number using python

http://www.cs.uni.edu/~diesburg/courses/cs1510_sp15/homework/PA04/index.htm
So I have this assignment. I have been trying to work out the code to find the additive and multiplicative roots of a user given input. I am new to python and know how to work the problem out, but without the tools (coding know how) have been just running in circles for quite a while now. So if anyone could be so kind as to help me figure out the coding. I have tried slicing the list, but keep getting an error if I try to make the string an int and if I leave it as an string it just doesn't seem to run. I know there is probably a way using modulous as well, but have yet to quite master it.
Thank you for any help any of you are able to leave me.
Edit
Here is the code I have so far.
import sys
userStr = input("What number should I use for my \
calculations? ")
userInt = int (userStr)
original = userStr #Save Copy of original value
originalTwo = userStr #Save second Copy of original value
addCount = 0
mulCount = 0
#Stop the program if the integer is less than or equal to 0
while userInt <= 0:
print ("Thanks for playing along!")
sys.exit()
#Use a while loop to repeat the process of splitting an integer into single digits and then adding the individual digits.
print = ("Addition")
while userInt > 9:
userInt = sum(map(int, userStr))
print("New Value: ",userStr)
addCount = addCount + 1
#Use a while loop to repeat the process of splitting an integer into single digits and then multiplying the individual digits.
print = ("Multiplication")
while original > 9:
original = (map (int, original))
print("New Value: ",original)
mulCount = mulCount + 1
#Print the outputs to the screen for the user.
print("For the Integer: ",userInt)
print(" Additive Persistence= ",addCount,", Additive Root= ", userInt)
print(" Multiplicative Persistence= ",mulCount,",
Multiplicative Root= ", original)

Reversing a number using recursion

I was tasked with reversing an integer recursively. I have an idea of how to formulate my base case but I'm unsure of what to put outside of the if statement. The parts I was unsure about are commented with question marks. With the first part, I don't know what to put and with the second part I'm unsure about whether it is correct or not.Thank you for the help.
Note: I'd like to avoid using external functions such as imports and things like these if possible.
def reverseDisplay(number):
if number < 10:
return number
return # ??????????
def main():
number = int(input("Enter a number: "))
print(number,end="") #???????????
reverseDisplay(number)
main()
I'm not going to give you the answer, but I'll give some hints. It looks like you don't want to convert it to a string -- this makes it a more interesting problem, but will result in some funky behavior. For example, reverseDisplay(100) = 1.
However, if you don't yet have a good handle on recursion, I would strongly recommend that you convert the input to a string and try to recursively reverse that string. Once you understand how to do that, an arithmetic approach will be much more straightforward.
Your base case is solid. A digit reversed is that same digit.
def reverseDisplay(n):
if n < 10:
return n
last_digit = # ??? 12345 -> 4
other_digits = # ??? You'll use last_digit for this. 12345 -> 1234
return last_digit * 10 ** ??? + reverseDisplay(???)
# ** is the exponent operator. If the last digit is 5, this is going to be 500...
# how many zeroes do we want? why?
If you don't want to use any string operations whatsoever, you might have to write your own function for getting the number of digits in an integer. Why? Where will you use it?
Imagine that you have a string 12345.
reverseDisplay(12345) is really
5 + reverseDisplay(1234) ->
4 + reverseDisplay(123) ->
3 + reverseDisplay(12) ->
2 + reverseDisplay(1) ->
1
Honestly, it might be a terrible idea, but who knows may be it will help:
Convert it to string.
Reverse the string using the recursion. Basically take char from the back, append to the front.
Parse it again.
Not the best performing solution, but a solution...
Otherwise there is gotta be some formula. For instance here:
https://math.stackexchange.com/questions/323268/formula-to-reverse-digits
Suppose you have a list of digits, that you want to turn into an int:
[1,2,3,4] -> 1234
You do this by 1*10^3 + 2*10^2 + 3*10^1 + 4.*10^0. The powers of 10 are exactly reversed in the case that you want to reverse the number. This is done as follows:
def reverse(n):
if n<10:
return n
return (n%10)*10**(int(math.log(n,10))) + reverse(n//10)
That math.log stuff simply determines the number of digits in the number, and therefore the power of 10 that should be multiplied.
Output:
In [78]: reverse(1234)
Out[78]: 4321
In [79]: reverse(123)
Out[79]: 321
In [80]: reverse(12)
Out[80]: 21
In [81]: reverse(1)
Out[81]: 1
In [82]: reverse(0)
Out[82]: 0
Does exactly what #GregS suggested in his comment. Key to reverse is to extract the last digit using the modulos operator and convert each extracted digit to a string, then simply join them back into the reverse of the string:
def reverseDisplay(number):
if number < 10:
return str(number)
return str(number % 10) + reverseDisplay(number / 10)
def main():
print (reverseDisplay(int(input("Enter a number: "))))
main()
Alternative method without using recursion:
def reverseDisplay(number):
return str(number)[::-1]

Resources