Read Bits for definded length at defined position - python

I have a bitstring.Bitarray and want to read from a certain position to another position.
I have the int variable length in a for loop, so for example I have:
length = 2
and my Bitarray looks something like:
msgstr = bitstring.BitArray(0b11110011001111110)
id = bitstring.BitArray()
m = 0
while 5 != m:
/////////////
Length changes in value part of Code
/////////////
x = 0
if m == 0:
while length != x:
id.append = msgstr[x] #msgstr is the BitArray that needs to be read
x = x + 1
m = m + 1
I then want to read the first two bits and convert them into an int, so that I have:
id == 3
And for the next round when length has changed in value it should start from the third bit etc.

The code inside your loop only does anything if m == 0, but then you increment m, so m is only 0 the first time through the loop. The rest of the times you go through your loop, it doesn't seem to actually be doing anything.
Also, where you say
id.append = msgstr[x]
you probably actually want
id.append(msgstr[x])
It also seems like you might benefit from using Python's slice notation.

I do not understand exactly what you goal is but do you had a look at https://wiki.python.org/moin/BitManipulation ?

Related

How to consistently slice the first and last character of a string in Python 3

I need help with writing a loop that can slice through a string, taking away the first and last character. I understand that the slice [0:-1] can target those two positions, but I need a way for it to iterate through the whole string. Here is a little snippet into what the output would ideally look like:
Input (min for length is 3) :
string = 'ABCDEFGHI'
Output:
['ABCDEFGHI', 'BCDEFGH', 'CDEFG']
I would be grateful for any guidance/advice!
Try this:
>>> [string[i:len(string)-i] for i in range(3)]
['ABCDEFGHI', 'BCDEFGH', 'CDEFG']
Here's a function you can use:
def foo(string, limit=None):
output = [string]
i = 0
if limit == None:
while i < len(string) / 2 - 1:
output.append(output[-1][1:-1])
i += 1
else:
while i < limit - 1:
output.append(output[-1][1:-1])
i += 1
return output
The second parameter can be used to set a limit to the length of the array. It is optional.

Python Optimizating the Van sequence

I am writing a code on python for the platform Coding Games . The code is about Van Eck's sequence and i pass 66% of the "tests".
Everything is working as expected , the problem is that the process runs out of the time allowed.
Yes , the code is slow.
I am not a python writer and I would like to ask you if you could do any optimization on the piece of code and if your method is complex ( Complex,meaning if you will be using something along vectorized data ) and not just swap an if (because that is easily understandable) to give a good explanation for your choice .
Here is my code for the problem
import sys
import math
def LastSeen(array):
startingIndex = 0
lastIndex = len(array) - 1
closestNum = 0
for startingIndex in range(len(array)-1,-1,-1):
if array[lastIndex] == array[startingIndex] and startingIndex != lastIndex :
closestNum = abs(startingIndex - lastIndex)
break
array.append(closestNum)
return closestNum
def calculateEck(elementFirst,numSeq):
number = numSeq
first = elementFirst
result = 0
sequence.append(first)
sequence.append(0)
number -= 2
while number != 0 :
result = LastSeen(sequence)
number -= 1
print(result)
firstElement = int(input())
numSequence = int(input())
sequence = []
calculateEck(firstElement,numSequence)
so here is my code without dictionaries. van_eck contains the sequence in the end. Usually I would use a dict to track the last position of each element to save runtime. Otherwise you would need to iterate over the list to find the last occurence which can take very long.
Instead of a dict, I simply initialized an array of sufficient size and use it like a dict. To determine its size keep in mind that all numbers in the van-eck sequence are either 0 or tell you how far away the last occurrence is. So the first n numbers of the sequence can never be greater than n. Hence, you can just give the array a length equal to the size of the sequence you want to have in the end.
-1 means the element was not there before.
DIGITS = 100
van_eck = [0]
last_pos = [0] + [-1] * DIGITS
for i in range(DIGITS):
current_element = van_eck[i]
if last_pos[current_element] == -1:
van_eck.append(0)
else:
van_eck.append(i - last_pos[current_element])
last_pos[current_element] = i

My python recursive function won't return and exceeds maximum recursive depth

I simply do not understand why this is not returning the value and stopping the recursion. I have tried everything but it seems to just keep on going no matter what I do. I am trying to get the program to get the loop to compare the first two values of the list if they are the same return that it was the first value. If they were not, add the first and second values of each list and compare, etc etc until it reaches the end of the list. If the sum of the values in each list never equal each other at any point then return 0.
It is supposed to take three inputs:
A single integer defining the length of the next two inputs
First set of input data
Second set of input data
Ex input
3
1 3 3
2 2 2
It should output a single number. In the case of the example data, it should output 2 because the sum of the lists equalled at the second value.
N = int(input())
s1 = input().split()
s2 = input().split()
count = 0
def func1(x,y):
if x == y:
return(count)
elif (N - 1) == count:
return(0)
else:
count + 1
return(func1(x + int(s1[count]), y + int(s2[count])))
days = func1(int(s1[0]),int(s2[0]))
print(days)
I am sorry in advance if I really messed up the formatting or made some dumb mistake, I am pretty new to programming and I have never posted on here before. Thanks in advance :)
The problem is that you never actually update the variable count. However, just writing:
count += 1
is not going to work either without declaring the variable global:
def func1(x, y):
global count
....
That said, global variables increase code complexity and break re-enterability, i.e. the same function can no longer be called twice, not to mention about concurrency. A much cleaner way is to make count a function argument, it will look like this (the code not tested and is here for illustration only):
N = int(input())
s1 = [int(c) for c in input().split()]
s2 = [int(c) for c in input().split()]
def func1(x, y, count=0):
if x == y:
return count
elif count == N - 1:
return 0
else:
return(func1(x + s1[count], y + s2[count]), count + 1)
days = func1(int(s1[0]),int(s2[0]))
print(days)
To answer "How would you go about solving this problem then" – If I understood the problem correctly, the aim is to find the index where the "running total" of the two lists is the same. If so,
def func1(s1, s2):
total_a = 0
total_b = 0
for i, (a, b) in enumerate(zip(s1, s2)):
total_a += a
total_b += b
if total_a == total_b:
return i
return 0
print(func1([1, 3, 3], [2, 2, 2]))
does the trick. (I've elided the input bits here – this function just works with two lists of integers.)

lightly alter a hash programmatically

At the moment I frequently have to do something in unittests with hashes and cryptographic signatures. Sometimes they get generated, and I just need to alter one slightly and prove that something no longer works. They are strings of hex-digits 0-9 and a-f of specific length. Here is a sample 64 long:
h = '702b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91a'
I want to change just one character somewhere in there.
You can't be sure that every digit 0 - 9 and a - f will be in there, although would guess it's at least 95% certain that they all are. If you could be sure, I would just run h = h.replace('a', 'b', 1) on it.
If you do it manually, you can just look at it and see the third digit is 2 and run:
new = list(h)
new[2] = '3'
h = ''.join(new)
But if you cannot see it and it needs to happen programmatically, what is a clean and certain way to change just one character in it somewhere?
from random import randrange
h = '702b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91a'
i = randrange(len(h))
new_h = h[:i] + hex(int(h[i], 16) + randrange(1, 16))[-1:] + h[i+1:]
In words:
choose a random index i in h
split the string into the part before the index, the char at the index, and the rest
replace the char at the index with its hex value incremented by a random int between 1 and 15, modulo 16 (i.e., its rightmost hex character)
build the new string from the above pieces
Note that an increment by a value between 1 and 15 (included), followed by a modulo 16, never maps a hex digit onto itself. An increment by 0 or 16 would map it exactly onto itself.
You can just choose a random index
import random
valid_chars = '0...f'
def replace_hash(hash_digest):
idx_to_replace = random.randint(64)
char_to_replace = hash_digest[idx_to_replace]
replacements = valid_chars.replace(char_to_replace, '')
hash_digest[idx_to_replace] = replacements[random.randint(15)
return hash_digest
The most efficient way is to just replace the first char with 1 of 2 replacements. I mean, you can only collide with one char anyway so there's no need to do it randomly. But if you want a random change the function'll work.
I suggest you increment the last character of the hash (cycling to 0 after f). That way you are sure to get a different hash, only differing by one character.
You can easily extend this method to change a character at the position of your choosing, and not just the last one.
h = '702b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91a'
def change_hash(h, index=-1):
digits = list(h)
old_digit= digits[index]
v = int(old_digit, 16)
new_v = (v+1)%16
new_digit = '{:x}'.format(new_v)
digits[index] = new_digit
return ''.join(digits)
print(change_hash(h))
# 702b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91b
# ^
print(change_hash(h, 2))
# 703b31faad0246cc89a5dc782cdf5235a885d0f529fb30a4e1e70e00938df91a
# ^
EDIT:
added option to change a digit at an arbitrary position
formatting the digit using format() as it was proposed in another answer
h = chr(ord(h[0]) + ((-1) if (h[0] in "9z") else 1)) + h[1:]

Variable nesting in Python

Basically, I need to make my program able to create multiple (unlimited) variables for me, that I will still be able to use manipulate through my code, without me defining them.
I was thinking to have a letter and a number as the variable name, such as a1, and have the program create new variables just adding 1 to the number. So it would create a1 through a30 or so. How would I do this?
My program is going to add polynomials and the variables (or list now) is to separate the different monomials, and since I don't know how many monomials there will be in the polynomial, I needed a way to make the number flexible so I have an exact amout of spaces for the monomials, no extras, and no less.
Here's the code:
# Sample polynomial set to x, the real code will say x = (raw_input("Enter a Polynomial")).
x = '(5xx + 2y + 2xy)+ (4xx - 1xy)'
# Isdigit command set to 't' to make the code easier to write.
t = str.isdigit
# Defining v for later use.
v = 0
# Defining 'b' which will be the index number that the program will look at.
b = 1
# Creating 'r' to parse the input to whatever letter is next.
r = x [b]
# Defining n which will be used later to tell if the character is numeric.
n = 0
# Defining r1 which will hold one of the monomials, ( **will be replaced with a list**)
#This was the variable in question.
r1 = ''
# Setting 'p' to evaluate if R is numeric ( R and T explained above).
p = t(r)
# Setting 'n' to 1 or 0 to replace having to write True or False later.
if p == True:
n = 1
else:
n = 0
# Checking if r is one of the normal letters used in Algebra, and adding it to a variable
if r == 'x':
v = 'x'
c = 1
elif r == 'y':
v = 'y'
c = 1
elif r == 'z':
v = 'z'
c = 1
# If the character is a digit, set c to 0, meaning that the program has not found a letter yet (will be used later in the code).
elif n == 1:
v = r
c = 0
# Adding what the letter has found to a variable (will be replaced with a list).
r1 = r1 + v
b = b + 1
I will eventually make this a loop.
I added comments to the code so it's more understandable.
Essentially, you are trying to programmatically, dynamically modify the heap space where the variables live. I really do not think this is possible. If it is, it is very obscure.
I do understand where you are coming from. When I was first learning to program I had thought to solve problems in ways that would require such "dynamically created" variables. The solution really is to recognize what kind of (collection) data structure fits your needs.
If you want variables a1 through a30, create a list a. Then a1 would be a[1], a30 would be a[30]. It is a little different to write, but it should give you the behavior you need.
I spent at least five minutes trying to think why you would want to do this in the first place, until I decided I could actually write the code in less than five minutes, and hoping that in return you'd tell us why you want to do this.
Here's the code:
def new(value):
highest = -1
for name in globals():
if name.startswith('a'):
try:
number = int(name[1:])
except:
continue
if number > highest:
highest = number
globals()['a%d' % (highest + 1, )] = value
new("zero")
new("one")
new("two")
print a2 # prints two

Categories