rounding off to next multiple of 5 in python - python-3.x

when we round 67 to its next multiple of 5 the answer is 70
where as when we round 64 the ans should be 65 but it comes to be 70
I looked for logic in C++
where I found 5*(grades[i]+4)/5) for calculation of next multiple of 5
my code implemented in python is:
ground=[]
grades=[73,64,67,38,33]
for i in range(len(grades)):
r=5*(round((grades[i]+4)/5))
ground.append(r)
print(ground)
expected output:[75,65,70,40,35]
but
actual output:[75,70,70,40,35]

Try this, This can be an optimised solution:
ground=[]
grades=[73,64,67,38,33]
for i in range(len(grades)):
temp = 5 - grades[i] % 5
ground.append(grades[i] + temp)
print(ground)

You should use the // operator (or int) instead of round:
ground = []
grades = [73, 64, 67, 38, 33]
for i in range(len(grades)):
r = 5 * ((grades[i] + 4) // 5)
ground.append(r)
print(ground)
Output:
[75, 65, 70, 40, 35]

Use modulo arithmetic on negative numbers to your advantage for this.
def round_up(n, base):
return n + (-n % base)
grades= [73, 64, 67, 38, 33]
rgrades = [round_up(n, 5) for n in grades] # [75, 65, 70, 40, 35]
This works on float and other number types.
round_up(70.5, 5) # 75.0

Related

Return range of integer list based on input number

I found this question in my test today, I have been trying to find correct answer for this but failing to do so.
Question is:
Imagine we have range of page numbers lets say 0, 100. When we click on page lets say 15, we only what to show 10 pages on UI i.e. from page 10 to 20
more example input: 50 output: returns list
[46,47,48,49,50,51,52,53,54,55]
input: 15
output: returns list
[11,12,13,14,15,16,17,18,19,20]
also list should include first page and last page i.e. 0 and 50
so the actual output would be for first example
[0,46,47,48,49,50,51,52,53,54,55,100]
Below is what I have tried
def get_thread_page_num(num, max_page_num):
# Returns 10 numbers dynamically
new_lst =[1,50]
# default list
# defult_lst = [1,2,3,4,5,6,7,8,9,10]
num -4 > 0
num+5 <max_page_num
i = 10
m = 4
p = 5
while i != 0:
if num-1 >0 and m !=0:
new_lst.append(num-m)
i=i-1
m = m-1
elif num+1<max_page_num and p != 0:
new_lst.append(num+p)
i=i-1
p = p-1
print(sorted(new_lst))
get_thread_page_num(9, 50)
In your code m and p starts with value 4 and 5 respectively. In every iteration, either of them decreases by 1. So, after 9 iteration both of them are 0 and new_lst contains 9 elements. Also i becomes 10-9 = 1.
But i never becomes 0 and the loop becomes infinite.
You can try below code instead. Please refer to the comments.
def get_thread_page_num(num, max_page_num):
# low and high denotes the low and high end of the list
# where middle element is num
low = max(0, num - 4)
high = min(num + 5, max_page_num)
lst = []
if max_page_num < 9:
# 10 element list is not possible
return lst
# In case high is same as max, just make the list as
# high-9, high -8, ..., high
if high == max_page_num:
lst = list(range(max(0, high - 9), high + 1))
else:
# Just create a list starting from low like -
# low, low + 1, ..., low + 9
lst = list(range(low, low+10))
# Add 0 and max if not already present
if 0 not in lst:
lst.append(0)
if max_page_num not in lst:
lst.append(max_page_num)
# return sorted lst
return sorted(lst)
Call to get_thread_page_num():
print(get_thread_page_num(15, 50))
print(get_thread_page_num(0, 50))
print(get_thread_page_num(2, 50))
print(get_thread_page_num(50, 50))
print(get_thread_page_num(43, 50))
Output:
[0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 50]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 50]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 50]
[0, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
[0, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50]

How to iterate over a Tensor in Tensorflow and change its values if necessary?

Assume I have a Tensor in TensorFlow of shape [600, 11]. All the elements of the last (11th) column are zero. I want to iterate over the values of the Tensor like that: For each row, I check whether the maximum of the first 10 elements of the row is greater than a value X. If True, then keep the row unchanged, if False, then set the first 10 elements of the row to be equal to zero and make the 11th element equal to 1. How can I do that? The structure of my Tensor is shown below:
import tensorflow as tf
a = tf.zeros([600, 1], dtype=tf.float32)
b = tf.random.uniform([600,10], minval=0, maxval=1, dtype=tf.float32)
c = tf.concat([b, a], axis=1)
You cannot iterate through tensors, nor set the value of individual elements. Tensors are immutable, so you always have to build a new tensor from the previous one instead. This is how you can do something like what you describe:
import tensorflow as tf
def modify_matrix(matrix, X):
all_but_last_column = matrix[:, :-1]
max_per_row = tf.reduce_max(all_but_last_column, axis=1)
replace = tf.concat([tf.zeros_like(all_but_last_column),
tf.ones_like(matrix[:, -1])[:, tf.newaxis]], axis=1)
mask = max_per_row > X
return tf.where(mask, matrix, replace)
nums = [list(range(i * 10, (i + 1) * 10)) + [0] for i in range(1, 5)]
print(*nums, sep='\n')
# [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0]
# [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0]
# [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0]
# [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0]
matrix = tf.constant(nums)
X = tf.constant(36, dtype=matrix.dtype)
result = modify_matrix(matrix, X)
print(sess.run(result))
# [[ 0 0 0 0 0 0 0 0 0 0 1]
# [ 0 0 0 0 0 0 0 0 0 0 1]
# [30 31 32 33 34 35 36 37 38 39 0]
# [40 41 42 43 44 45 46 47 48 49 0]]
I also found another solution that it worked for me:
import tensorflow as tf
zeroes = tf.zeros([600, 1], dtype=tf.float32)
ones = tf.ones([600, 1], dtype=tf.float32)
b = tf.random.uniform([600,10], minval=0, maxval=1, dtype=tf.float32)
threshold = tf.constant(0.6, dtype=tf.float32)
check = tf.reduce_max(tf.cast(b > threshold, dtype=tf.float32), axis=1)
last_col = tf.where(check>0, zeroes, ones)
new_b = tf.where(check>0, b, tf.zeros([600, 10], dtype=tf.float32))
new_matrix = tf.concat([new_b, last_col], axis=1)

How to print a 3x3 2D array using elements from a list in python 3?

I have wrote a code that displays a list.
import random
def Rand(start, end, num):
res = []
for j in range(num):
res.append(random.randint(start, end))
return res
num = 9
start = 1
end = 100
numbers = [(Rand(start, end, num))]
print(numbers)
The output is 9 random numbers in a list.
[[10, 32, 86, 84, 46, 91, 71, 52, 7]]
I would like to print random numbers in a 3x3 2D array.
10 32 86
84 46 91
71 52 7
I'll skip the randomization part as it is not relevant to your question. In general, to split a list into n-sized chunks, you can simply slice the list while iterating the index in n steps:
numbers = [10, 32, 86, 84, 46, 91, 71, 52, 7]
n = 3
print([numbers[i:i+n] for i in range(0, len(numbers), n)])
This outputs:
[[10, 32, 86], [84, 46, 91], [71, 52, 7]]
Or if you want the output to look like a 3x3 2D array:
print('\n'.join(' '.join(map(str, numbers[i:i+n])) for i in range(0, len(numbers), n)))
This outputs:
10 32 86
84 46 91
71 52 7
Note that the numbers variable in your question holds a list of a list of numbers, rather than a list of numbers. You should make the assignment numbers = Rand(start, end, num) instead without unnecessarily enclosing it in another list.

How to break repeating-key XOR Challenge using Single-byte XOR cipher

This Question is about challenge number 6 in set number 1 in the challenges of "the cryptopals crypto challenges".
The challenge is:
There's a file here. It's been base64'd after being encrypted with repeating-key XOR.
Decrypt it.
After that there's a description of steps to decrypt the file, There is total of 8 steps. You can find them in the site.
I have been trying to solve this challenge for a while and I am struggling with the final two steps. Even though I've solved challenge number 3, and it contains the solution for these steps.
Note: It is, of course, possible that there is a mistake in the first 6 steps but they seems to work well after looking at the print after every step.
My code:
Written in Python 3.6.
In order to not deal with web requests, and since it is not the purpose of this challenge. I just copied the content of the file to a string in the begging, You can do this as well before running the code.
import base64
# Encoding the file from base64 to binary
file = base64.b64decode("""HUIfTQsP...JwwRTWM=""")
print(file)
print()
# Step 1 - guess key size
KEYSIZE = 4
# Step 2 - find hamming distance - number of differing bits
def hamming2(s1, s2):
"""Calculate the Hamming distance between two bit strings"""
assert len(s1) == len(s2)
return sum(c1 != c2 for c1, c2 in zip(s1, s2))
def distance(a, b): # Hamming distance
calc = 0
for ca, cb in [(a[i], b[i]) for i in range(len(a))]:
bina = '{:08b}'.format(int(ca))
binb = '{:08b}'.format(int(cb))
calc += hamming2(bina, binb)
return calc
# Test step 2
print("distance: 'this is a test' and 'wokka wokka!!!' =", distance([ord(c) for c in "this is a test"], [ord(c) for c in "wokka wokka!!!"])) # 37 - Working
print()
# Step 3
key_sizes = []
# For each key size
for KEYSIZE in range(2, 41):
# take the first KEYSIZE worth of bytes, and the second KEYSIZE worth of bytes -
# file[0:KEYSIZE], file[KEYSIZE:2*KEYSIZE]
# and find the edit distance between them
# Normalize this result by dividing by KEYSIZE
key_sizes.append((distance(file[0:KEYSIZE], file[KEYSIZE:2*KEYSIZE]) / KEYSIZE, KEYSIZE))
key_sizes.sort(key=lambda a: a[0])
# Step 4
for val, key in key_sizes:
print(key, ":", val)
KEYSIZE = key_sizes[0][1]
print()
# Step 5 + 6
# Each line is a list of all the bytes in that index
splited_file = [[] for i in range(KEYSIZE)]
counter = 0
for char in file:
splited_file[counter].append(char)
counter += 1
counter %= KEYSIZE
for line in splited_file:
print(line)
print()
# Step 7
# Code from another level
# Gets a string and a single char
# Doing a single-byte XOR over it
def single_char_string(a, b):
final = ""
for c in a:
final += chr(c ^ b)
return final
# Going over all the bytes and listing the result arter the XOR by number of bytes
def find_single_byte(in_string):
helper_list = []
for num in range(256):
helper_list.append((single_char_string(in_string, num), num))
helper_list.sort(key=lambda a: a[0].count(' '), reverse=True)
return helper_list[0]
# Step 8
final_key = ""
key_list = []
for line in splited_file:
result = find_single_byte(line)
print(result)
final_key += chr(result[1])
key_list.append(result[1])
print(final_key)
print(key_list)
Output:
b'\x1dB\x1fM\x0b\x0f\x02\x1fO\x13N<\x1aie\x1fI...\x08VA;R\x1d\x06\x06TT\x0e\x10N\x05\x16I\x1e\x10\'\x0c\x11Mc'
distance: 'this is a test' and 'wokka wokka!!!' = 37
5 : 1.2
3 : 2.0
2 : 2.5
.
.
.
26 : 3.5
28 : 3.5357142857142856
9 : 3.5555555555555554
22 : 3.727272727272727
6 : 4.0
[29, 15, 78, 31, 19, 27, 0, 32, ... 17, 26, 78, 38, 28, 2, 1, 65, 6, 78, 16, 99]
[66, 2, 60, 73, 1, 1, 30, 3, 13, ... 26, 14, 0, 26, 79, 99, 8, 79, 11, 4, 82, 59, 84, 5, 39]
[31, 31, 19, 26, 79, 47, 17, 28, ... 71, 89, 12, 1, 16, 45, 78, 3, 120, 11, 42, 82, 84, 22, 12]
[77, 79, 105, 14, 7, 69, 73, 29, 101, ... 54, 70, 78, 55, 7, 79, 31, 88, 10, 69, 65, 8, 29, 14, 73, 17]
[11, 19, 101, 78, 78, 54, 100, 67, 82, ... 1, 76, 26, 1, 2, 73, 21, 72, 73, 49, 27, 86, 6, 16, 30, 77]
('=/n?3; \x00\x13&-,>1...r1:n\x06<"!a&n0C', 32)
('b"\x1ci!!>ts es(ogg ...5i<% tc:. :oC(o+$r\x1bt%\x07', 32)
('??:<+6!=ngm2i4\x0byD...&h9&2:-)sm.a)u\x06&=\x0ct&~n +=&*4X:<(3:o\x0f1<mE gy,!0\rn#X+\nrt6,', 32)
('moI.\'ei=Et\'\x1c:l ...6k=\x1b m~t*\x155\x1ei+=+ts/e*9$sgl0\'\x02\x16fn\x17\'o?x*ea(=.i1', 32)
('+3Enn\x16Dcr<$,)\x01...i5\x01,hi\x11;v&0>m', 32)
[32, 32, 32, 32, 32]
Notice that in the printing of the key as string you cannot see it but there is 5 chars in there.
It is not the correct answer since you can see that in the forth part - after the XOR, the results do not look like words... Probably a problem in the last two functions but I couldn't figure it out.
I've also tried some other lengths and It does not seems to be the problem.
So what I'm asking is not to fix my code, I want to solve this challenge by myself :). I would like you to tell me where I am wrong? why? and how should I continue?
Thank you for your help.
After a lot of thinking and checking the conclusion was that the problem is in step number 3. The result was not good enough since I looked only at the first two blocks.
I fixed the code so it will calculate the KEYSIZE according to all of the blocks.
The code of Step 3 now look like this:
# Step 3
key_sizes = []
# For each key size
for KEYSIZE in range(2, 41):
running_sum = []
for i in range(0, int(len(file) / KEYSIZE) - 1):
running_sum.append(distance(file[i * KEYSIZE:(i + 1) * KEYSIZE],
file[(i + 1) * KEYSIZE:(i + 2) * KEYSIZE]) / KEYSIZE)
key_sizes.append((sum(running_sum)/ len(running_sum), KEYSIZE))
key_sizes.sort(key=lambda a: a[0])
Thanks for any one who tried to help.

Trying to generate primes from 1 - n, but consistently is missing primes 3 and 5.?

def generate_primes(n):
"""generate_primes(n) -> list
Returns a list of all primes <= n."""
from math import sqrt
primes = [2]
potentialPrimes = []
for x in range(3, n + 1):
potentialPrimes.append(x)
if x % 2 == 0:
potentialPrimes.remove(x)
currentPrime = potentialPrimes[0]
primes.append(currentPrime)
while currentPrime < sqrt(n):
for x in potentialPrimes:
if x % currentPrime == 0:
potentialPrimes.remove(x)
currentPrime = potentialPrimes[0]
for x in potentialPrimes:
primes.append(x)
print(primes)
generate_primes(100)
When I try to call the function, it prints this:
[2, 3, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Any idea why?
And any ways to improve my code would be much appreciated as well.
In while loop you set currentPrime =5 but dont remove it from potential primes, so in next iteration potentialPrimes[0] is still 5. And 5%5==0 so it removes it from potential primes and does the same with 7.
Here's code in the same style, but correctly showing all of the numbers
def generate_primes(n):
from math import sqrt
primes=[]
potentialPrimes=range(2,n+1)
prime=potentialPrimes[0]
while prime<sqrt(n):
primes.append(prime)
potentialPrimes.remove(prime)
for potential in potentialPrimes:
if potential%prime==0:
potentialPrimes.remove(potential)
prime=potentialPrimes[0]
for potential in potentialPrimes:
primes.append(potential)
for number in primes:
print number
Removing items from a list as you iterate it is never a good idea
for x in potentialPrimes:
if x % currentPrime == 0:
potentialPrimes.remove(x)

Resources