did my code is in a short-circuit way ( python3) - python-3.x

How would we adapt it to return True if at least three of the numbers are odd? Short-circuit the traversal when
the third odd number is found — don’t traverse the whole list unless we have to.
****I am a novice in python, I want to know the time is taken more when I use ==,<= operators why? did this code stop traversing after find the 3 odd?****
import time
start_time = time.time()
def d(x):
count = 0
for num in x:
if num % 2 != 0:
count += 1
if count <= 3:
return True
return False
print((time.time() - start_time))
f = d([1,2,4,6,8,7,3,11,16,88,66,44,22])
print((time.time()-start_time),f)

I don't know if I got you right but I can propose some changes in your code. First - if you want to count number of odd numbers and return True if number of odds is <= 3. you can do it like that:
>>> def count_odds(lst: list):
... count = 0
... for num in lst:
... count += 1 if num % 2 else 0
... return count <= 3
...
>>> count_odds([1, 3, 5, 6])
True
>>> count_odds([1, 3, 7, 9, 11])
False
This function will return True only if there are 3, 2, 1 or 0 odd numbers in list that you've passed to this method.
On the other hand you can achieve your goal by using break in the for loop. Here is the solution:
>>> lst = [1, 3, 5, 7]
>>> count = 0
>>> for num in lst:
... if count > 3:
... break
... count += 1 if num % 2 else 0
>>> print("More than 3") if count > 3 else print("Less than 3")
Less than 3
# Rest of your code.
And another way to do it:
>>> def count_odds(lst: list):
... result = list(map(lambda x: x % 2, lst))
... return sum(result) <= 3
...
>>> count_odds([1, 3, 7])
True
>>> count_odds([1, 3, 7, 9])
False
The map function takes every element of the lst list, then returns True if element is odd, False otherwise. Then the sum function sums all the True values of the result list and gives you the answer.

Related

How many times should I loop to cover all cases of possible sums?

I am trying to solve this competitive programming problem using python3. The problem asks, given an array of size n, split the array into three consecutive, contiguous parts such that the first part has maximum sum and equals the sum of the third part. The elements in the array are positive integers.
My approach:
inputN = int(input())
inputString = input()
usableString = stringToList(inputString)
counting = 0
sum1 = usableString[0]
sum3 = usableString[-1]
maxSum1 = 0
countFromLeft = 1
countFromRight = 2
while counting < inputN-1:
if sum1 > sum3:
sum3 += usableString[-countFromRight]
countFromRight += 1
elif sum3 > sum1:
sum1 += usableString[countFromLeft]
countFromLeft += 1
elif sum1 == sum3:
maxSum1 = sum1
sum1 += usableString[countFromLeft]
countFromLeft += 1
counting += 1
print(maxSum1)
We read in the array elements and store them in a list usableString.
We set two variables sum1 and sum3 to the first and last elements of the list respectively.
We set a variable to keep track of the maximum sum of the first part of the list.
Finally, we set a variable counting to 0 which will represent the number of elements we have added from the list into sum1 or sum3.
The rest of the logic is in the while loop, which just checks if sum1 is larger than sum3 or the other way around and otherwise if they equal. After each iteration we add 1 to counting as an extra element has been included in a part. The while loop should stop when the number of elements used (i.e counting) is equal to the number of elements in the array - 1, since we added the first and last elements before entering the loop, which makes (array - 2), however, we still need to loop one additional time to check if sum1 and sum3 are equal.
I checked your submitted algorithm, and the problem is your stringToList function:
def stringToList(s):
list=[]
for elem in s:
if elem != " ":
list.append(int(elem))
return list
As far as I can tell, your main algorithm is completely fine, but stringToList does one crucial thing incorrectly:
>>> stringToList('2 4 6 8 10')
[2, 4, 6, 8, 1, 0]
# should be
[2, 4, 6, 8, 10]
As it treats each character individually, the two digits of 10 are turned into 1, 0. A simpler method which performs correctly would be to do the following:
# explanation
>>> input()
'2 4 6 8 10'
>>> input().split(' ')
['2', '4', '6', '8', '10']
>>> map(int, input().split(' ')) # applies the int function to all elements
<map object at 0x...>
>>> list(map(int, input().split(' '))) # converts map object into list
[2, 4, 6, 8, 10]
Sorry it took so long, I ended up making my own algorithm to compare to yours, ran my own tests, and then ran your code with the input to list method I just explained, and figured the only difference was your stringToList function. Took a while, but I hope it helps!
Just for the fun, here's my algorithm and turns out it was pretty similar to yours!
array = [1, 3, 2, 1, 4]
n = len(array)
slice = [0, n]
sum = [array[0], 0]
bestSum = 0
while slice[0] < slice[1]-1:
i = 0 if (sum[0] < sum[1]) else 1
slice[i] += 1-(2*i)
sum[i] += array[slice[i]]
if sum[0] == sum[1]: bestSum = sum[0]
# print(array[ : slice[0]+1], array[slice[0]+1 : slice[1]], array[slice[1] : ])
print(bestSum)

Finding subset List of Python List based on an input integer

I want a subset list from input List based on input integer value.
For Example:
Input List: [3,7,9,11,12]
Input Value: 2
Output List: [1,7,9,11,12]
# 2 is subtracted from first element of list
Input List: [3,7,9,11,12]
Input Value: 5
Output List: [5,9,11,12]
#5 is subtracted from list in sequence manner, first 3 is subtracted then remaining 2 is subtracted from 7 hence output is [5,9,11,12]
Use numpy.cumsum() if modules are allowed:
import numpy as np
input_list = np.asarray([3, 7, 9, 11, 12])
input_integer = 5
output_list = input_list[input_list.cumsum() > input_integer]
output_list[0] -= input_integer - input_list[input_list.cumsum() <= input_integer].sum()
print(output_list)
Output:
[ 5 9 11 12]
What i did there:
Since total sum is to be subtracted from starting, using cumulated sum will tell you where to crop the list from.
Then set the first element = first elem - (input_integer - cropped list's sum)
Recursive solution:
def subfrom( lst, n ):
if n<=0 or lst == []:
# No change necessary
return lst
if lst[0] <= n:
# First element gets removed
# Return the list you get by removing the leftover from the rest of the list
return subfrom( lst[1:], n-lst[0] )
# Reducde first element
return [lst[0]-n] + lst[1:]
Another solution:
# First set of test variables
list1 = [3,7,9,11,12]
input1 = 2
# Second set of test variables
list2 = [3,7,9,11,12]
input2 = 5
def eval_list(input_value, iterable, output = None):
if output is None:
output = []
for i, v in enumerate(iterable):
current = iterable[i]
if input_value > 0:
if v <= input_value:
input_value -= current
else:
current -= input_value
input_value = 0
output.append(current)
else:
output.append(current)
return output
Run for each data set and output results:
res1 = eval_list(input1, list1)
res2 = eval_list(input2, list2)
print(f"Set 1: {res1}")
print(f"Set 2: {res2}")
Output:
Set 1: [1, 7, 9, 11, 12]
Set 2: [5, 9, 11, 12]

Index Error: list index out of range (Python beginner, while loops)

I am trying to make a function that takes in a list as an input parameter. I am to use a while loop to iterate over the list and keep track of the amount of integers and strings that are included in the list. This is what i have so far:
def usingwhileloop(mylist):
count = 0
int_total = 0
str_total = 0
while count <= len(mylist):
if isinstance(mylist[count], int) == True:
int_total = int_total + 1
elif isinstance((mylist[count]), str) == True:
str_total = str_total + 1
count = count + 1
newlist = [int_total, str_total]
return newlist
When I run for a list like [1, 2, 3, “a”, “b”, 4] it should return [4, 2] but instead i get the following error: "line 51, in usingwhileloop
if isinstance(what[count], int) == True:
IndexError: list index out of range"
what am i doing wrong? I struggle with while loops...
It's because you were trying to access an item from the list that doesn't exist.
Why? Assuming we're using this list as example - [1, 2, 3, “a”, “b”, 4]
count starts from 0 so I assume you expect count to go from 0 to 5.
0: 1
1: 2
2: 3
3: "a"
4: "b"
5: 4
However, len(mylist) is 6 so the loop will attempt to access mylist[6] which does not exist.
You have to modify your while loop to stop at 5 instead. To do that, while count <= len(mylist) - 1: or while count < len(mylist): will do.
If you really require a while loop then see the answer by josephting.
For the example that you have shown though, you don't need a while loop, e.g.
"""
Some simple functions
"""
def count_types_ex1(items):
"""Count types from a list"""
counters = [0, 0]
for item in items:
if isinstance(item, int):
counters[0] += 1
elif isinstance(item, str):
counters[1] += 1
return counters
print(count_types_ex1([1, 2, 3, 'a', 'b', 4]))
def count_types_ex2(items):
"""Count types from a list"""
check_type = lambda x: [int(isinstance(x, int)), int(isinstance(x, str))]
counters = [check_type(x) for x in items]
return sum(x[0] for x in counters), sum(x[1] for x in counters)
print(count_types_ex2([1, 2, 3, 'a', 'b', 4]))
Output:
[4, 2]
(4, 2)

Recursive function to sum the elements in the list

Even though it looks not difficult, it makes me crazy.
I couldn't even get close to an answer.
Can you guys give me any help?
Write a recursive function sums_to(nums, k) that takes a list of integers and returns True if the
sum of all the elements in the list is equal to k and returns Falseotherwise.
Example:
>>> nums = [1, 2, 3]
>>> sums_to(nums, 6)
True
>>> sums_to(nums, 5)
False
>>> sums_to([], 1)
False
Note: You are not allowed to use any python sum function in any form, nor sum the list and then at
the end check whether it equals k. In addition, you must write sums_to as a single recursive function:
That is, you may not use a main function and a recursive helper function.
# my pool code
def sums_to(nums, k):
if nums == []:
return False
if nums[0] + sums_to(nums[1:], k) == k:
return True
This is what I tried so far.
Sadly, I could not think of a hint to give. The whole problem is about that return statement:
def sums_to(nums, k):
if not nums:
return k == 0
return sums_to(nums[:-1], k - nums[-1])
print(sums_to([1, 2, 3], 6))
print(sums_to([1, 2, 3], 5))
print(sums_to([], 1))
You can do this using recursion, you have two case, if the list is empty, or not:
def sums_to(nums , n):
if len(nums) == 0:
return n == 0
else:
m = nums[0]
nums.pop(0)
return sums_to(nums, (n-m))
print(sums_to([2,3], 5))

Define Python function that returns True if the values in the input list alternately go up and down(in a strict manner)

def alternating(l):
f=0
if len(l)==0 or len(l)==1:
f=1
for i in range(0,len(l)):
if i==len(l)-3:
break
if l[i]<l[i+1]:
if l[i+1]>l[i+2]:
f=1
if l[i]>l[i+1]:
if l[i+1]<l[i+2]:
f=1
if f==1:
return(True)
if f==0:
return(False)
I have tried this logic but not working.
i want to solve this problem.
returns True if the values in the input list alternately go up and down.
You can use itertools.cycle with operator.lt and operator.gt here to handle which delta you wish to check next and pair up each adjacent elements using zip, then use the builtin all function to make sure that all comparisons are True, eg:
from itertools import cycle
from operator import lt, gt
def is_alternating(seq):
# First element must be less, next must be more, repeat...
# (can be changed to lt, lt, lt, gt or whatever pattern is required)
ops = cycle([lt, gt])
# Zip the ops and the pairs of numbers
it = zip(ops, zip(seq, seq[1:]))
# Check that all operations return True - will short circuit on False
return all(f(a, b) for f, (a, b) in it)
for sequence in [[1, 3, 2], [1], [], [1, 2, 3, 4], [2, 4, 1, 5, 3, 7]]:
print(sequence, '->', is_alternating(sequence))
Gives you:
[1, 3, 2] -> True
[1] -> True
[] -> True
[1, 2, 3, 4] -> False
[2, 4, 1, 5, 3, 7] -> True
I believe this will do what you're after.
This code works both ways up -> down -> up and down -> up -> down
def is_alternating(lst):
# check if list is valid
if len(lst) < 3:
return False
# get stating direction
# first element > second = up -> down
# up is True, down is False
direction = lst[0] > lst[1]
for i in range(len(lst) - 1):
if direction:
if not lst[i] > lst[i + 1]:
return False
else:
if not lst[i] < lst[i + 1]:
return False
# invert direction
direction = not direction
return True
# Output
>>> is_alternating( [1, 2, 3, 4] )
False
>>> is_alternating( [1, 2, 0, 4] )
True
>>> is_alternating( [5, 2, 8, 4] )
True
We define alternating as each pair of elements ((s[0],s[1]), (s[1],s[2]) ... ) to have the opposite relation (a<b) then the previous/next pairs. Also if any pair are equal to each other then the sequence is not alternating, meaning the exact function would look like this:
from itertools import tee
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def alternating(seq):
last = None
for a,b in pairwise(seq):
if a==b or (a<b) == last:
return False
else:
last = a<b
return True
note that this would return True for sequences with 2 or less elements, if that is not the desired behaviour you would need to add a if len(seq)<3:return False although then this method would not work with iterators like generators.
Start from index i element and compare with previous and next element with it.
I check if element at index i greater than previous and next element or if it is less than previous and next element.
If one of the condition become False then list does not contain alternating elements.
def alternating(l):
if l == [] or len(l) == 1:
return True
for i in range(1,len(l)-1):
if l[i] > l[i-1]:
if not l[i] > l[i+1]:
return False
elif l[i] < l[i-1]:
if not l[i] < l[i+1]:
return False
return True
Did the following steps.-
1. -If the length of list is 0 or 1, return false.
2. if two adjacent element of the list is same then return false.
3. checking the consistency of the list, if it is alternating or not.
4. If not then return false otherwise return true.
def alternating(l): # l is a list !
if len(l) == 0 or len(l) == 1:
return True
for i in range(len(l)-1):
if l[i]==l[i+1]:
return False
for i in range(2,len(l)):
if l[i-2]>l[i-1] :
if (l[i]<l[i-1]):
return False
elif l[i-2]<l[i-1]:
if (l[i] > l[i - 1]):
return False
return True
def alternating(l):
a=b=c=d=0
if len(l)==0 or len(l)==1 or (len(l)==2 and l[0]!=l[1]):
return ("True")
for i in range(0,len(l)-1,2):
if(l[i]<l[i+1]):
a+=1
if(l[i]>l[i+1]):
b+=1
if a!=len(l)//2 and b!= len(l)//2:
return("False")
for i in range(1,len(l)-1,2):
if(l[i]<l[i+1]):
c+=1
if(l[i]>l[i+1]):
d+=1
if c!=(len(l)-1)//2 and d!= (len(l)-1)//2:
return("False")
if a==d or b==c:
return("True")
return("False")
list1 = list()
n = int(input("How many numbers you want to enter in list:"))
for i in range(n):
ele = int(input())
list1.append(ele)
print(list1)
if(list1[0]==9 or list1[1]== 9 or list1[2]==9 or list1[3]==9):
print("True")
else:
print("False")
def alternating(x):
if len(x)==0:
return(True)
for i in range(0,len(x)-2):
if x[i]==x[i+2]:
return(True)
else:
return(False)

Resources