converting C code to Python by hand - python

Im am trying to covert the following C code to Python. I have no experience in C but a little in Python.
main( int argc, char *argv[])
{
char a[] = "ds dsf ds sd dsfas";
unsigned char c;
int d, j;
for(d = 0; d < 26; d++)
{
printf("d = %d: ", d);
for (j = 0; j < 21; j++ )
{
if( a[j] == ' ')
c = ' ';
else
{
c = a[j] + d;
if (c > 'z')
c = c - 26;
}
printf("%c", c);
}
printf("\n");
}
I have managed to up to this point: Where I get an list index out of range exception, any suggestions?
d=0
a=["ds dsf ds sd dsfas"]
while (d <26):
print("d = ",d)
d=d+1
j=0
while(j<21):
if a[j]=='':
c =''
else:
c = answer[j]+str(d)
if c>'z':
c=c-26
j=j+1
print("%c",c)

I hope this does what your C code is trying to achieve:
#! /usr/bin/python2.7
import string
a = 'ds dsf ds sd dsfas' #input
for d in range (26): #the 26 possible Caesar's cypher keys
shift = string.ascii_lowercase [d:] + string.ascii_lowercase [:d] #rotate the lower ase ascii with offset d
tt = string.maketrans (string.ascii_lowercase, shift) #convenience function to create a transformation, mapping each character to its encoded counterpart
print 'd = {}:'.format (d) #print out the key
print a.translate (tt) #translate the plain text and print it

the loop executes till j becomes 21.But I dont think you have that many elements in the a list. Thats why you get the error. I think len(a) is 18. So changing the loop as:
while j<len(a):
#code
or
while j<18:
#code
Will clear the error

See this, It's been explained with comments:
d=0
a=["ds dsf ds sd dsfas"]
# this will print 1 as a is a list object
# and it's length is 1 and a[0] is "ds dsf ds sd dsfas"
print len(a)
# and your rest of program is like this
while (d <26):
print("d = ",d)
d=d+1
#j=0
# while(j<21): it's wrong as list length is 1
# so it will give list index out of bound error
# in c array does not check for whether array's index is within
# range or not so it will not give out of bound error
for charValue in a:
if charValue is '':
c =''
else:
c = charValue +str(d) # here you did not initialized answer[i]
if c>'z':
c=c-26
#j=j+1
print("%c",c)

Related

Looping in list (get first after the last)

I'm trying to make an easy dummy thing but I kinda stopped at something i never encounter. Making some kind of translator which should work like this:
word = "hello"
h => i (+1 position in alphabet)
e => g (+2)
l => o (+3)
l => p (+4)
o => t (+5)
but I (obviously) hit the end of the list at some point. Is there some kind of function(maybe) to loop the list?
To work it like this:
word = "maze"
m = n (+1)
a = c (+2)
z = c (+3 - loop thru the list to the start)
e = i (+4)
I was thinking of using -26 as the indexerror exception, but I'm kinda hoping there is going to be more beautiful posibility. Or maybe even easier solution overall?
Thanks!
Code:
import string
alphabet_list = []
word = "hello my friend"
x = 0
for char in string.ascii_lowercase:
alphabet_list.append(char)
### 26 chars || 0 - 25 ###
# print(alphabet_list)
for character in word:
x += 1
if character in alphabet_list:
print(alphabet_list[alphabet_list.index(character) + x])
Using modulo % operator. This will work for lowercase letters from a to z:
def code(s):
a = ord('a')
return ''.join( chr(a + ((ord(c) - a) + i) % 26) for i, c in enumerate(s, 1) )
def decode(s):
a = ord('a')
return ''.join( chr(a + ((ord(c) - a) - i) % 26) for i, c in enumerate(s, 1) )
coded_string = code('maze')
print(coded_string)
print(decode(coded_string))
Prints:
ncci
maze

C function to Python (different results)

I am trying to port this snippet of code to python from C. The outputs are different even though it's the same code.
This is the C version of the code which works:
int main(void)
{
uint8_t pac[] = {0x033,0x55,0x22,0x65,0x76};
uint8_t len = 5;
uint8_t chan = 0x64;
btLeWhiten(pac, len, chan);
for(int i = 0;i<=len;i++)
{
printf("Whiten %02d \r\n",pac[i]);
}
while(1)
{
}
return 0;
}
void btLeWhiten(uint8_t* data, uint8_t len, uint8_t whitenCoeff)
{
uint8_t m;
while(len--){
for(m = 1; m; m <<= 1){
if(whitenCoeff & 0x80){
whitenCoeff ^= 0x11;
(*data) ^= m;
}
whitenCoeff <<= 1;
}
data++;
}
}
What I currently have in Python is:
def whiten(data, len, whitenCoeff):
idx = len
while(idx > 0):
m = 0x01
for i in range(0,8):
if(whitenCoeff & 0x80):
whitenCoeff ^= 0x11
data[len - idx -1 ] ^= m
whitenCoeff <<= 1
m <<= 0x01
idx = idx - 1
pac = [0x33,0x55,0x22,0x65,0x76]
len = 5
chan = 0x64
def main():
whiten(pac,5,chan)
print pac
if __name__=="__main__":
main()
The problem i see is that whitenCoeff always remain 8 bits in the C snippet but it gets larger than 8 bits in Python on each loop pass.
You've got a few more problems.
whitenCoeff <<= 1; is outside of the if block in your C code, but it's inside of the if block in your Python code.
data[len - idx -1 ] ^= m wasn't translated correctly, it works backwards from the C code.
This code produces the same output as your C code:
def whiten(data, whitenCoeff):
for index in range(len(data)):
for i in range(8):
if (whitenCoeff & 0x80):
whitenCoeff ^= 0x11
data[index] ^= (1 << i)
whitenCoeff = (whitenCoeff << 1) & 0xff
return data
if __name__=="__main__":
print whiten([0x33,0x55,0x22,0x65,0x76], 0x64)
In C you are writing data from 0 to len-1 but in Python you are writing data from -1 to len-2. Remove the -1 from this line:
data[len - idx -1 ] ^= m
like this
data[len - idx] ^= m
you also need to put this line outside the if:
whitenCoeff <<= 1
whitenCoeff <<= 1 in C becomes 0 after a while because it is a 8-bit data.
In python, there's no such limit, so you have to write:
whitenCoeff = (whitenCoeff<<1) & 0xFF
to mask higher bits out.
(don't forget to check vz0 remark on array boundary)
plus there was an indentation issue.
rewritten code which gives same result:
def whiten(data, whitenCoeff):
idx = len(data)
while(idx > 0):
m = 0x01
for i in range(0,8):
if(whitenCoeff & 0x80):
whitenCoeff ^= 0x11
data[-idx] ^= m
whitenCoeff = (whitenCoeff<<1) & 0xFF
m <<= 0x01
idx = idx - 1
pac = [0x33,0x55,0x22,0x65,0x76]
chan = 0x64
def main():
whiten(pac,chan)
print(pac)
if __name__=="__main__":
main()
Slightly off-topic: Note that the C version already has problems:
for(int i = 0;i<=len;i++)
should be
for(int i = 0;i<len;i++)
I solved it by anding the python code with 0xFF. That keeps the variable from increasing beyond 8 bits.
Your code in C does not appear to work as intended since it displays one more value than is available in pac. Correcting for this should cause 5 values to be displayed instead of 6 values. To copy the logic from C over to Python, the following was written in an attempt to duplicate the results:
#! /usr/bin/env python3
def main():
pac = bytearray(b'\x33\x55\x22\x65\x76')
chan = 0x64
bt_le_whiten(pac, chan)
print('\n'.join(map('Whiten {:02}'.format, pac)))
def bt_le_whiten(data, whiten_coeff):
for offset in range(len(data)):
m = 1
while m & 0xFF:
if whiten_coeff & 0x80:
whiten_coeff ^= 0x11
data[offset] ^= m
whiten_coeff <<= 1
whiten_coeff &= 0xFF
m <<= 1
if __name__ == '__main__':
main()
To simulate 8-bit unsigned integers, the snippet & 0xFF is used in several places to truncate numbers to the proper size. The bytearray data type is used to store pac since that appears to be the most appropriate storage method in this case. The code still needs documentation to properly understand it.

python: read integer's from stream step by step

I can in Python:
n = int(input())
a = [int(x) for x in input().split()]
I can in c++:
int main()
{
int n, x;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> x;
somthing(x)
}
}
How to write it on Python (3.x)? Can I handle the numbers in the flow without saving all in list?
Input data (for example):
6
1 4 4 4 1 1
Can I use sys.stdin?
UPD:
Ok, I wrote this:
import sys
n = int(input())
i = 0
c = ""
s = ""
while i < n:
c = sys.stdin.read(1)
if c in [" ","\n"]:
x = int(s)
somthing(x)
s = ""
i += 1
else:
s += c
Is there a more elegant solution?
Python doesn't special-case such a specific form of input for you. By default, the input() function then reads a line from input (delimited by newline character) and converts it to a string.
You'll have to use the split() to separate the values.

Python equivalent to program in C

My goal is to translate the following written in C, into python, so I can evaluate the loop over a string of digits. Originally, the objective takes a range from 0 to 9, gathers input for each iteration while also multiplying, and sums the entire range. Last of all, determines the remainder after dividing by 11.
int checksum(char *str) {
int i, sum = 0;
for (i=0; i<9; i++) {
sum+= (str[i] - '0') * (i + 1);
}
return sum % 11;
}
A direct (but not very idiomatic) translation of the code would look as follows, notice that I renamed some of the variables to avoid clashes with Python's built-in functions:
def checksum(s):
c = 0
for i in range(9):
c += int(s[i]) * (i + 1)
return c % 11
Another more Pythonic option would be to use generator expressions instead of explicit loops:
def checksum(s):
return sum(int(e) * i for i, e in enumerate(s[:9], 1)) % 11

Need help porting C function to Python

I'm trying to port a C function which calculates a GPS checksum over to Python. According to the receiving end I am sometimes miscalculating the checksum, so must still have a bug in there.
C code is
void ComputeAsciiChecksum(unsigned char *data, unsigned int len,
unsigned char *p1, unsigned char *p2)
{
unsigned char c,h,l;
assert(Stack_Low());
c = 0;
while (len--) {
c ^= *data++;
}
h = (c>>4);
l = c & 0xf;
h += '0';
if (h > '9') {
h += 'A'-'9'-1;
}
l += '0';
if (l > '9') {
l += 'A'-'9'-1;
}
*p1 = h;
*p2 = l;
}
My attempt at a Python function is
def calcChecksum(line):
c = 0
i = 0
while i < len(line):
c ^= ord(line[i]) % 256
i += 1
return '%02X' % c;
Here is how you can set up a testing environment to diagnose your problem.
Copy the above C function to a file, remove the assert() line, and compile it to a shared library with
gcc -shared -o checksum.so checksum.c
(If you are on Windows or whatever, do the equivalent of the above.)
Copy this code to a Python file:
import ctypes
import random
c = ctypes.CDLL("./checksum.so")
c.ComputeAsciiChecksum.rettype = None
c.ComputeAsciiChecksum.argtypes = [ctypes.c_char_p, ctypes.c_uint,
ctypes.c_char_p, ctypes.c_char_p]
def compute_ascii_checksum_c(line):
p1 = ctypes.create_string_buffer(1)
p2 = ctypes.create_string_buffer(1)
c.ComputeAsciiChecksum(line, len(line), p1, p2)
return p1.value + p2.value
def compute_ascii_checksum_py(line):
c = 0
i = 0
while i < len(line):
c ^= ord(line[i]) % 256
i += 1
return '%02X' % c;
Now you have access to both versions of the checksum function and can compare the results. I wasn't able to find any differences.
(BTW, how are you computing the length of the string in C? If you are using strlen(), this would stop at NUL bytes.)
As a side note, your Python version isn't really idiomatic Python. Here are two more idiomatic versions:
def compute_ascii_checksum_py(line):
checksum = 0
for c in line:
checksum ^= ord(c)
return "%02X" % checksum
or
def compute_ascii_checksum_py(line):
return "%02X" % reduce(operator.xor, map(ord, line))
Note that these implementations should do exactly the same as yours.
Have you checked out this cookbook recipe? It hints at what input you should include in "line", returns a asterisk in front of the checksum, and gives one (input, output) data pair that you can use as test data.
Are you sure that "the receiver" is working correctly? Is the problem due to upper vs lower case hex letters?

Categories