Splitting number into 2 lists of numbers of certain range - python-3.x

I want to create 2 lists of numbers, generated randomly with certain range.
So, if user want to generate lists as above from value 1000 (example) it should split 1000 into 2 lists:
1st list - 4 numbers in range from 40 to 80
2nd list - 5 numbers in range from 80 to 160
Sum of all produced list numbers must equal input (or hardcoded number, doesn't matter). Main range of input 560 - 1120.
Python 3.7 actually, and some problems in declaring that
See code below, I've managed to generate random 2 lists of certain range but I don't have idea how to work that out that it can have declared sum and split it into lists rather than generating random lists all together.
import random
def function():
num = 4
start = 40
end = 80
def rand(start, end, num):
res = []
for j in range(num):
res.append(random.randint(start,end))
return res
return rand(start, end, num)
def function2():
num2 = 5
start2 = 80
end2 = 160
def rand2(start2, end2, num2):
res2 = []
for k in range(num2):
res2.append(random.randint(start2,end2))
return res2
return rand2(start2, end2, num2)
a = function()
b = function2()
print (a)
print (sum(a))
print(b)
print(sum(b))
suma = sum(a+b)
print (suma)
If anyone could help me solving that I'd be really glad, I'm making a little project and this is required :)

Related

find the first occurrence of a number greater than k in a sorted array

For the given sorted list,the program should return the index of the number in the list which is greater than the number which is given as input.
Now when i run code and check if it is working i am getting 2 outputs. One is the value and other output is None.
If say i gave a input of 3 for the below code.The expected output is index of 20 i.e., 1 instead i am getting 1 followed by None.
If i give any value that is greater than the one present in the list i am getting correct output i.e., "The entered number is greater than the numbers in the list"
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a,num_to_find):
j = i = 0
while j==0:
if a[len(a)-1] > num_to_find:
if num_to_find < a[i]:
j=1
print(i)
break
else:
i = i + 1
else:
ret_state = "The entered number is greater than the numbers in the list"
return ret_state
print(occur1(a,num_to_find))
This code is difficult to reason about due to extra variables, poor variable names (j is typically used as an index, not a bool flag), usage of break, nested conditionals and side effect. It's also inefficient because it needs to visit each element in the list in the worst case scenario and fails to take advantage of the sorted nature of the list to the fullest. However, it appears working.
Your first misunderstanding is likely that print(i) is printing the index of the next largest element rather than the element itself. In your example call of occur1([2, 20, 30], 3)), 1 is where 20 lives in the array.
Secondly, once the found element is printed, the function returns None after it breaks from the loop, and print dutifully prints None. Hopefully this explains your output--you can use return a[i] in place of break to fix your immediate problem and meet your expectations.
Having said that, Python has a builtin module for this: bisect. Here's an example:
from bisect import bisect_right
a = [1, 2, 5, 6, 8, 9, 15]
index_of_next_largest = bisect_right(a, 6)
print(a[index_of_next_largest]) # => 8
If the next number greater than k is out of bounds, you can try/except that or use a conditional to report the failure as you see fit. This function takes advantage of the fact that the list is sorted using a binary search algorithm, which cuts the search space in half on every step. The time complexity is O(log(n)), which is very fast.
If you do wish to stick with a linear algorithm similar to your solution, you can simplify your logic to:
def occur1(a, num_to_find):
for n in a:
if n > num_to_find:
return n
# test it...
a = [2, 5, 10]
for i in range(11):
print(i, " -> ", occur1(a, i))
Output:
0 -> 2
1 -> 2
2 -> 5
3 -> 5
4 -> 5
5 -> 10
6 -> 10
7 -> 10
8 -> 10
9 -> 10
10 -> None
Or, if you want the index of the next largest number:
def occur1(a, num_to_find):
for i, n in enumerate(a):
if n > num_to_find:
return i
But I want to stress that the binary search is, by every measure, far superior to the linear search. For a list of a billion elements, the binary search will make about 20 comparisons in the worst case where the linear version will make a billion comparisons. The only reason not to use it is if the list can't be guaranteed to be pre-sorted, which isn't the case here.
To make this more concrete, you can play with this program (but use the builtin module in practice):
import random
def bisect_right(a, target, lo=0, hi=None, cmps=0):
if hi is None:
hi = len(a)
mid = (hi - lo) // 2 + lo
cmps += 1
if lo <= hi and mid < len(a):
if a[mid] < target:
return bisect_right(a, target, mid + 1, hi, cmps)
elif a[mid] > target:
return bisect_right(a, target, lo, mid - 1, cmps)
else:
return cmps, mid + 1
return cmps, mid + 1
def linear_search(a, target, cmps=0):
for i, n in enumerate(a):
cmps += 1
if n > target:
return cmps, i
return cmps, i
if __name__ == "__main__":
random.seed(42)
trials = 10**3
list_size = 10**4
binary_search_cmps = 0
linear_search_cmps = 0
for n in range(trials):
test_list = sorted([random.randint(0, list_size) for _ in range(list_size)])
test_target = random.randint(0, list_size)
res = bisect_right(test_list, test_target)[0]
binary_search_cmps += res
linear_search_cmps += linear_search(test_list, test_target)[0]
binary_search_avg = binary_search_cmps / trials
linear_search_avg = linear_search_cmps / trials
s = "%s search made %d comparisons across \n%d searches on random lists of %d elements\n(found the element in an average of %d comparisons\nper search)\n"
print(s % ("binary", binary_search_cmps, trials, list_size, binary_search_avg))
print(s % ("linear", linear_search_cmps, trials, list_size, linear_search_avg))
Output:
binary search made 12820 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 12 comparisons
per search)
linear search made 5013525 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 5013 comparisons
per search)
The more elements you add, the worse the situation looks for the linear search.
I would do something along the lines of:
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a, num_to_find):
for i in a:
if not i <= num_to_find:
return a.index(i)
return "The entered number is greater than the numbers in the list"
print(occur1(a, num_to_find))
Which gives the output of 1 (when inputting 3).
The reason yours gives you 2 outputs, is because you have 2 print statements inside your code.

Wanted a failing test case for code for Subset with maximum sum so that no two elements in it are adjacent to each other

Given a multi-set of non-zero integers find a multi-subset of integers with maximum sum such that no two elements in this multi-subset are adjacent to each other. If there are at least two such multi-subsets then that multi-subset is chosen whose smallest element is the largest of all smallest elements in the candidate multi-subsets.
I saw solutions for finding the maximum sum, but I want the actual multi-subset too. Also, I don't want code; I just want a failing test case for my code.
Input is in the following format.
T positive integer (# of test cases)
N1 (positive integer followed by N1 integers representing the set whose "maximum sum" subset has to be identified)
a1 a2 a3 ... aN1
N2
...
NT
....
Output
a3a1 (required subset in reverse order - for example, a1 + a3 forms the largest sum in the first set above and so output is a3a1)
Concrete examples:
2
4
3 6 2 -2
4
4 5 3 4
Output
6
45
({4,4} and {3,5} both form the largest sum but 35 is not output because smallest element in {4,4} > smallest element in {5,3})
I wrote code and it passes on all test cases I can think of. But it fails a formal assessment and I don't know what the failing test cases are. My idea is the following. Either the first element F in the set is a member of the required subset or it is not. If it is, then we recursively find the "minimum sum" subset from the third element onwards in the original set and adjoin it to F. If it is not, then we recursively find this subset from the second element onwards of the original set.
Below is the code I wrote. Can someone give a failing test case?
#returns 1 if all but the first element are negative
def all_neg(t):
sum=0
for i in range(1,len(t)):
if t[i]<0:
sum+=1
if sum==len(t)-1:
return 1
#reverses string
def reverse(t):
if len(t)<=1:
return t
else:
l=[t[-1]]
l.extend(reverse(t[:-1]))
return l
def max(a1,a2):
if a1>a2:
return a1
else:
return a2
#returns the sum of the subset with the maximum sum
def sum_max(t):
if len(t)==0:
return 0
elif len(t)==1:
return (t[0])
elif len(t)==2:
if t[0]>t[1]:
return t[0]
else:
return t[1]
else:
if t[0]>0:
if sum_max(t[2:])>0:
c1=t[0]+sum_max(t[2:])
else:
c1=t[0]
else:
return sum_max(t[1:])
c2=sum_max(t[1:])
return(max(c1,c2))
#returns the subset with the maximum sum
def arr_max(t):
if len(t)<=1:
return t
elif len(t)==2:
if t[0]>t[1]:
return [t[0]]
else:
return [t[1]]
elif sum_max(t)>sum_max(t[1:]):
if all_neg(t[1:]):
return([t[0]])
l=[]
l.append(t[0])
tmp=arr_max(t[2:])
l.extend(arr_max(t[2:]))
return l
elif sum_max(t)==sum_max(t[1:]):
l=[]
if (t[0]<0):
return arr_max(t[1:])
l.append(t[0])
l.extend(arr_max(t[2:]))
m=arr_max(t[1:])
sl=sum(l)
sm=sum(m)
if sl>sm:
return l
elif sm>sl:
return m
lm=min(l)
mm=min(m)
if lm<mm:
return m
else:
return l
else:
return arr_max(t[1:])
def main():
test=int(input())
for i in range(0,test):
N=int(input())
t=[int(s) for s in input().split()]
y=arr_max(t)
print(''.join(str(i) for i in reverse(y)))
main()

Counting pairs of numbers that adds up to a specific value in Python

i want to count how many pairs of numbers in a list can add to a specific number, this is my code in python but the output is not what it should be
list = [1,2,3,4]
x=3
count = 0
for i in range(len(list)):
for j in range(len(list)):
if i + j == x:
count+=1
print(count)
You could simpilify your code with functions from the built-in itertools module, depending on how you would like to iterate through the list, i.e. combinations, combinations with replacements, or products.
import itertools as itt
in_list = [1,2,3,4]
tgt_num = 3
count = 0
for a,b in itt.combinations(in_list, 2): # returns 1
# for a,b in itt.combinations_with_replacement(in_list, 2): # returns 1
# for a,b in itt.product(in_list, in_list): # returns 2
if a + b == tgt_num:
count += 1
print(count)
Your code has some issues:
One is that it never directly references the items of the list. Because of this, it will only work assuming that the numbers in the list are in ascending order, each is one apart, and that it starts at 1.
Another is that it iterates through the pairs of numbers too many times.
Finally, there are some indentation issues, but I'm guessing those were just lost in the copy-paste. I tried to re-indent it, but when I ran it I got "4", when it should be "1".
Here's a version that incorporates indexing the list, which should resolve the above issues.
list = [1,2,3,4]
x = 3
count = 0
for i in range(0,len(list)):
pair1 = list[i]
pair2 = list[i+1:]
for j in range(0,len(pair2)):
if pair1 + pair2[j] == x:
count += 1
print(count)

Convert list of integers to a single integer : ValueError

I am trying to convert a list of integers in Python into a single integer say for example [1,2,3,4] to 1234(integer). In my function, I am using following piece of code:
L = [1,2,3,4]
b = int(''.join(map(str, L)))
return b
The compiler throws a ValueError. Why so? How to rectify this issue?
You can do this like this also if that cause problems:
L = [1,2,3,4]
maxR = len(L) -1
res = 0
for n in L:
res += n * 10 ** maxR
maxR -= 1
print(res)
1234
another solution would be
L = [1,2,3,4]
digitsCounter = 1
def digits(num):
global digitsCounter
num *= digitsCounter
digitsCounter *= 10
return num
sum(map(digits, L[::-1]))
the digits() is a non pure function that takes a number and places it on place value depending on the iteration calling digits on each iteration
1. digits(4) = 4 1st iteration
2. digits(4) = 40 2nd iteration
3. digits(4) = 400 3rd iteration
when we sum up the array returned by map from the inverted list L[::-1] we get 1234 since every digit in the array is hoisted to it place value
if we choose not no invert L array to L[::-1] then we would need our digits function to do more to figure out the place value of each number in the list so we use this to take adv of language features

python. finding largest integer in string

Write the function largestNumber(text) that takes a string of text and returns the largest int value that occurs within that text, or None if no such value occurs.
For example:
largestNumber("I saw 3 dogs, 17 cats, and 14 cows!")
returns 17 (the int value 17, not the string "17").
and
largestNumber("One person ate two hot dogs!")
returns None (the value None, not the string "None").
I tried using isdigit function to separate out integer but how can I compare string?
You can try using a regex, and then max and map functions:
result = [e for e in re.split("[^0-9]", "I saw 3 dogs, 17 cats, and 14 cows!") if e != '']
# list 'result' elements are strings: ['3', '17', '14'], so we use map(int, list) to get integers
print max(map(int, result))
You could also do
def largestNumber(in_str):
l=[int(x) for x in in_str.split() if x.isdigit()]
return max(l) if l else None
First you split in_str based on space () with split() to get a list.
The 'numbers' in this list are identified using isdigit() and converted to integers using int().
These numbers are stored in l as a list.
The expression
max(l) if l else None
will give maximum value in l if l is not empty and otherwise None.
print(largestNumber("I saw 3 dogs, 17 cats, and 14 cows!"))
gives
17
and
print(largestNumber("One person ate two hot dogs!"))
gives
None
Just Another solution:
def findLargestNumber(text):
ls = list()
for w in text.split():
try:
ls.append(int(w))
except:
pass
try:
return max(ls)
except:
return None
print findLargestNumber('I saw 3 dogs, 17 cats, and 14 cows!')
print findLargestNumber('I saw ')
Output:
17
None
def findLargestNumber(text):
front = -1
li = []
for i in range(len(text)):
if front == -1:
if text[i].isdigit():
front = i
else:
continue
else:
if text[i].isdigit():
continue
else:
li.append(int(text[front:i+1]))
front = -1
return max(li)
print findLargestNumber('I saw 3 dogs, 17 cats, and 14 cows!')
import re
def extractmax(str1):
nums=re.findall("\d+",str1)
return max(nums)
\d+ is used to look for a decimal or number with length greater than one, it is appended into the array nums finally maximum value from nums if generated.
The following worked for me, and it works great!
Increment number in the string and then print out the max number in string
import re
import re
Increase number in string
name = "name 1"
number = re.search(r'\d+', str(name))
if number:
rx = r'(?<!\d){}(?!\d)'.format(number.group())
prefix = re.sub(rx, lambda x: str(int(x.group()) + 1), name)
print(prefix)
Instead of just printing this row directly "re.sub(rx, lambda x: str(int(x.group()) + 1), name)"
Store it in a variable, in my case prefix
That's because you will get the updated value in the string and not the original
Store incremented variable "name" into a list
li = [int(prefix[5:])]
print("Largest name", max(li))
Keep in mind that index 5 is where the number is starting, you may need to adjust it depending on the string length
You can try to make 2 variables to see if the max method is working properly

Resources