What I'm trying to do is taking the even indexes of a list then adding them together and lastly multiplying the total with the last element in the list. When I try with a set of negative numbers then suddenly its multiplying with index[1]
def checkio(array: list) -> int:
"""
sums even-indexes elements and multiply at the last
"""
total = 0
evennumbs = []
if len(array) == 0:
return 0
for i in array:
if array.index(i) % 2 == 0:
evennumbs.append(i)
for e in evennumbs:
#print(total, " + ", e, " = ")
total += e
print(evennumbs)
print(total)
total = total * array[-1]
return total
# These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
(checkio([-37,-36,-19,-99,29,20,3,-7,-64,84,36,62,26,-76,55,-24,84,49,-65,41]))
#assert checkio([0, 1, 2, 3, 4, 5]) == 30, "(0+2+4)*5=30"
#assert checkio([1, 3, 5]) == 30, "(1+5)*5=30"
#assert checkio([6]) == 36, "(6)*6=36"
#assert checkio([]) == 0, "An empty array = 0"
This is the output I'm getting
[-37, -19, 29, 3, -64, 36, 26, 55, -65]
-36
-36 is the number it's multiplying with instead of 41.
Your function would be simplified a lot using slicing:
def checkio(array: list) -> int:
if not array:
return 0
return sum(array[::2])*array[-1]
assert checkio([0, 1, 2, 3, 4, 5]) == 30, "(0+2+4)*5=30"
assert checkio([1, 3, 5]) == 30, "(1+5)*5=30"
assert checkio([6]) == 36, "(6)*6=36"
assert checkio([]) == 0, "An empty array = 0"
Aside from the useless need for loops in your solution, this bit in particular is incorrect:
for i in array:
if array.index(i) % 2 == 0:
evennumbs.append(i)
this would fail on input such as [1,2,3,3] or [1,2,2,3] as list.index always returns the first occurrence
array.index(i) returns the index of the first occurrence of i in array. The first occurrence of the value 84 in your test array is on an odd index, although it later occurs on an even index as well, and so you are losing it.
You should probably simply loop over the indices directly.
for i in range(0, len(array)+1, 2):
evennumbs.append(array[i])
But of course, this can be simplified to just
evennumbs = array[::2]
and so the entire function can be simplified to
from typing import List
def checkio(array: List[int]) -> int:
if len(array) == 0:
return 0
return sum(array[::2]) * array[-1]
Related
What the code does: Takes a Python list of integers as input and searches for a 'symmetrical' inner-portion of the list.
Examples of what i want:
symmetrical_sum([10,11,12,11,12]) == ([11, 12, 11], 34)
symmetrical_sum([9,99,88,8,77,7,77,8,88,10,100]) == ([88, 8, 77, 7, 77, 8, 88], 353)
symmetrical_sum([10,8,7,5,9,8,15]) == ([8, 7, 5, 9, 8], 37)
Symmetry occurs if the value of the ith element from the start of the list is equal to the value of the ith element from the end of the list.
My Code:
def symmetrical_sum(a):
#extract duplicate value
dupe = [x for n, x in enumerate(a) if x in a[:n]]
#if no duplicate values found, do the following:
if dupe == []:
middle = float(len(a))/2
if middle % 2 != 0:
sym = a[int(middle - .5):int(middle + .5)]
ans = a[int(middle - .5)]
tuple1 = (sym,ans)
elif middle % 2 == 0:
sym = a[int(middle - 1):int(middle + 1)]
ans = sum(a[int(middle - 1):int(middle + 1)])//2
tuple1 = (sym,ans)
return tuple1
else:
d_to_i = int("".join(map(str, dupe))) #convert duplicate value to integer
p1 = a.index(d_to_i) #get index of first duplicate
p2 = a.index(d_to_i, p1+1) #get index of second duplicate
sym = a[p1:p2+1] #[symmetrical-portion]
ans = sum(sym) #sum-of-symmetrical-portion
tuple2 = (sym, ans)
return tuple2
My code works but it would be great if someone can post a way shorter solution for efficiency purposes, please.
x = [10,11,12,11,12]
output = [(x[n:-n],sum(x[n:-n])) for n in range(len(x)) if x[n] == x[-n-1]]
#this will output 3 cases: Symmetry regardless of even/odd elements. OR no symmetry for odd. (middle index)
if output == []:#even number of elements with no symmetry at all
pass
if len(output[0][0]) == 1: #odd number of elements with no symmetry at all
pass
print(output[0])
I hope this helps. I don't really understand what you do when no symmetry is detected. output will return all lists of symmetry and their sums including if there is no symmetry but odd number of elements. Not particularly sure if this is the optimal way to do what you want.
I have a list of elements and only one (odd number or even number) is different than others and I want as a result its index in the list.
For example:
nums = [2, 4, 6, 8, 7] or nums = [1, 3, 4, 5]
#how using only "for" loop not def (it is too difficult for me yet) do it?
for i,num in enumerate (nums):
if num % 2 == 1 and ... # I was thinking here of using a count function (I do not know how to tell python that in the same time it should be unique element
print (i)
elif if num % 2 == 0 and ...
print (i)
Please explain simply because I am very much a beginner in Python.
It's really hard to understand the scope of the problem, but if you simply want a majority vote (as in all numbers vote for the group being even or odd, then you might do something like this:
nums1 = [2,4,6,7,8]
nums2 = [2,1,3,5,7]
def get_one(nums):
nums_bin = [i%2 for i in nums]
if sum(nums_bin)>1:
return nums_bin.index(0)
return nums_bin.index(1)
print nums1, get_one(nums1)
print nums2, get_one(nums2)
# outputs
# [2, 4, 6, 7, 8] 3
# [2, 1, 3, 5, 7] 0
nums = [2, 4, 6, 8, 7]
#With the following line you take modulo 2 for each element so nums will become [0, 0, 0, 0, 1]
nums = [x%2 for x in nums]
#you still need to figure out, if the majority of elements was even or odd
#you can do that by checking the sum of the array. If it is 1, all but one element were even, if it is len(nums)-1 all but one were odd.
sum_of_nums = sum(nums)
for i in range(len(nums)):
#If the sum is ==1 you are looking for the one element that is 1
if nums[i] == 1 and sum_of_nums == 1:
print(i)
#If the sum is len(nums)-1 you are looking for the one element that is 0
if nums[i] == 0 and sum_of_nums == len(nums)-1:
print(i)
Now regarding the don't use def:
The def is used to define a function similar to what you know from mathmatics. f(x)=x+1 will work for f(1)=2 , f(2)=3 in a similar way you def = define a function that takes an input (Math -> the x, here -> an array of Integers) and does something to it (Math -> Add 1, here -> find the element)
The syntax is def functionName (inputParameter):
for the code above:
def yourFunction (nums):
for i in range(len(nums)):
#If the sum is ==1 you are looking for the one element that is 1
if nums[i] == 1 and sum_of_nums == 1:
print(i)
#If the sum is len(nums)-1 you are looking for the one element that is 0
if nums[i] == 0 and sum_of_nums == len(nums)-1:
print(i)
You can now do the following:
nums1 = [2, 4, 3]
nums2 = [3, 5, 8]
and just call:
yourFunction(nums1) and it will print 2
yourFunction(nums2) and it will print 2
I will try to explain the question step by step, and as requested, I will try to avoid defining functions or list comprehensions at first, and try to explain how to go from for to list comprehension or defining functions.
We start with our list nums, and we define two empty lists. In one we will store the positions of the even numbers in nums and in the other the position of the odd ones:
#nums = [2, 4, 6, 8, 7]
nums = [1, 3, 4, 5]
odds = []
evens = []
for i,num in enumerate (nums):
if num % 2 == 1:
odds.append(i)
elif num % 2 == 0:
evens.append(i)
The, we will print the list of length 1:
if len(odds)==1:
print odds[0]
elif len(evens)==1: # or else:
print evens[0]
There is an elif instead of an else to check that there is indeed only one number different to the rest, but it could be substituted by an else.
Now to simplify and make the code a little more pythonic.
The creation of the odds and evens list can be written in the same line, using list comprehensions. Thus, the for loop can be simplified to only 2 lines:
odds = [i for i,num in enumerate(nums) if num % 2 == 1]
evens = [i for i,num in enumerate(nums) if num % 2 == 0]
Then, if you have more than one list to check, it will be interesting to wrap all the commands up to the print in a function. With this, simply calling this function defined by you, all the commands will be executed at once.
Functions are defined with the def command, followed by function_name(input1,input2...):, at the end, there is the option of placing a line containing return output1,output2.... In this case, there is only one input, the list of numbers, and one output, the index of the odd/even one out, therefore:
def oddeven_one_out(num_list):
odds = [i for i,num in enumerate(nums) if num % 2 == 1]
evens = [i for i,num in enumerate(nums) if num % 2 == 0]
if len(odds)==1:
result = odds[0]
elif len(evens)==1:
result = evens[0]
return result
Now, the function can be called for each list:
nums1 = [1, 3, 4, 5]
print oddeven_one_out(nums1)
nums2 = [2, 4, 6, 8, 7]
print oddeven_one_out(nums2)
The function defined has one little problem though, which is that if the user makes a mistake and enters a list where all numbers are even, the variable result will not be defined, and return will raise an error.
This can be easily solved and will help in understanding the return command. When the function encounters a return, it leaves, without executing the code that may be below. Using this behaviour, we can redefine the function:
def oddeven_one_out(num_list):
odds = [i for i,num in enumerate(nums) if num % 2 == 1]
if len(odds)==1:
return odds[0]
evens = [i for i,num in enumerate(nums) if num % 2 == 0]
if len(evens)==1:
return evens[0]
Now the function checks if there is only one odd number, and if it is the case, returns its position, otherwise checks if the different one is even and if so returns its position. In addition, if the user calls oddeven_one_out([1,3,5,7]), the result will be None because the function does not return any value.
I am trying to perform a binary search on a list in python. List is created using command line arguments. User inputs the number he wants to look for in the array and he is returned the index of the element. For some reason, the program only outputs 1 and None. Code is below.
Any help is extremely appreciated.
import sys
def search(list, target):
min = 0
max = len(list)-1
avg = (min+max)/2
while (min < max):
if (list[avg] == target):
return avg
elif (list[avg] < target):
return search(list[avg+1:], target)
else:
return search(list[:avg-1], target)
print "The location of the number in the array is", avg
# The command line argument will create a list of strings
# This list cannot be used for numeric comparisions
# This list has to be converted into a list of ints
def main():
number = input("Please enter a number you want to search in the array !")
index = int(number)
list = []
for x in sys.argv[1:]:
list.append(int(x))
print "The list to search from", list
print(search(list, index))
if __name__ == '__main__':
main()
CL :
Anuvrats-MacBook-Air:Python anuvrattiku$ python binary_search.py 1 3 4 6 8 9 12 14 16 17 27 33 45 51 53 63 69 70
Please enter a number you want to search in the array !69
The list to search from [1, 3, 4, 6, 8, 9, 12, 14, 16, 17, 27, 33, 45, 51, 53, 63, 69, 70]
0
Anuvrats-MacBook-Air:Python anuvrattiku$
In Python2 and Python3 you can use bisect as written in the comments.
Replace your search with the following
from bisect import bisect_left
def search(alist, item):
'Locate the leftmost value exactly equal to item'
i = bisect_left(alist, item)
if i != len(alist) and alist[i] == item:
return i
raise ValueError
alist = [1,2,7,8,234,5,9,45,65,34,23,12]
x = 5
alist.sort() # bisect only works on sorted lists
print(search(alist, x)) # prints 2 as 5 is on position 2 in the sorted list
Also, the AS SortedCollection (Python recipe) could be useful.
The following code (from here) performs the binary search and returns position and if the item was found at all.
def binarySearch(alist, item):
first = 0
last = len(alist)-1
found = False
while first<=last and not found:
pos = 0
midpoint = (first + last)//2
if alist[midpoint] == item:
pos = midpoint
found = True
else:
if item < alist[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return (pos, found)
Will return (2, True) if used in the example above.
Well, there are some little mistakes in your code. To find them, you should either use a debugger, or at least add traces to understand what happens. Here is your original code with traces that make the problems self evident:
def search(list, target):
min = 0
max = len(list)-1
avg = (min+max)/2
print list, target, avg
...
You can immediately see that:
you search in a sub array that skips avg-1 when you are below avg
as you search in a sub array you will get the index in that subarray
The fixes are now trivial:
elif (list[avg] < target):
return avg + 1 + search(list[avg+1:], target) # add the offset
else:
return search(list[:avg], target) # sublist ends below the upper limit
That's not all, when you end the loop with min == max, you do not return anything (meaning you return None). And last but not least never use a name from the standard Python library for your own variables.
So here is the fixed code:
def search(lst, target):
min = 0
max = len(lst)-1
avg = (min+max)/2
# uncomment next line for traces
# print lst, target, avg
while (min < max):
if (lst[avg] == target):
return avg
elif (lst[avg] < target):
return avg + 1 + search(lst[avg+1:], target)
else:
return search(lst[:avg], target)
# avg may be a partial offset so no need to print it here
# print "The location of the number in the array is", avg
return avg
Recursive:
def in_list(l, x):
if len(l) < 2:
if l[0] == x:
return True
else:
return False
mid = len(l) // 2
if x < l[mid]:
return in_list(l[:mid], x)
else:
return in_list(l[mid:], x)
or iterative:
def in_list2(l, x):
low = 0
high = len(l) - 1
while low <= high:
mid = (low + high) // 2
if l[mid] == x:
return True
if x < l[mid]:
high = mid - 1
else:
low = mid + 1
return False
#Serge Ballesta 's solution is undoubtly the correct answer to this question.
I am just going to add another way of solving this:
def search(arr, item, start, end):
if end-start == 1:
if arr[start] == item:
return start
else:
return -1;
halfWay = int( (end-start) / 2)
if arr[start+halfWay] > item:
return search(arr, item, start, end-halfWay)
else:
return search(arr, item, start+halfWay, end)
def binarysearch(arr, item):
return search(arr, item, 0, len(arr))
arr = [1, 3, 4, 6, 8, 9, 12, 14, 16, 17, 27, 33, 45, 51, 53, 63, 69, 70]
print("Index of 69: " + str(binarysearch(arr, 69))) # Outputs: 16
The reason you aren't getting correct result is because in every recursive call your code is sending sliced array. So the array length keeps reducing. Ideally you should work out a way to send original array and work with only start, end indices.
I wrote this code for a simple linear search:
def floor(array, target):
i = 0
while i < len(array):
if array[i] == target:
print("The target value can be found at index: " + str(array[i]))
break
else:
i = i + 1
floor([1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14], 5)
The problem I'm having is that it's not returning the values I want. For some reason it doesn't start counting at 0, so when I make the target 1 it tells me the index is 1. Likewise, if I make the target 4 it will give me the second value of 4 at index 4 rather than the one at index 3. Even when the target is a higher number, it only seems to count the value of 4 once. I'm not sure what I'm doing wrong, can anyone offer some advice?
You're printing out the value at the index ie array[i] instead of i.
You're printing the value of the array at the index instead of the index itself. This fixes it. Also consider a return instead of a print statement.
def floor(array, target):
i = 0
while i < len(array):
if array[i] == target:
print("The target value can be found at index: " + str(i))
return i
else:
i = i + 1
four_ind = floor([1, 2, 3, 4, 4, 5, 6, 7, 8, 9], 4) # returns 3
try this:
def floor(array, target):
for i, value in enumerate(array):
if value == target:
print('target is in:', i)
floor([1,2,3,4,5, 4, 4,6], 4)
I am having trouble getting the results to produce the integer in the list, not which index it falls under.
#this function takes, as input, a list of numbers and an option, which is either 0 or 1.
#if the option is 0, it returns a list of all the numbers greater than 5 in the list
#if the option is 1, it returns a list of all the odd numbers in the list
def splitList(myList, option):
#empty list for both possible options
oddList = []
greaterList = []
#if option is 0, use this for loop
if int(option) == 0:
#create for loop the length of myList
for i in range(0, len(myList)):
#check if index is greater than 5
if ((myList[i])>5):
#if the number is greater than 5, add to greaterList
greaterList.append(i)
#return results
return greaterList
#if option is 1, use this for loop
if int(option) == 1:
#create for loop the length of myList
for i in range(0, len(myList)):
#check if index is odd by checking if it is divisible by 2
if ((myList[i])%2!=0):
#if index is not divisible by 2, add the oddList
oddList.append(i)
#return results
return oddList
the results I receive are as follows:
>>>splitList([1,2,6,4,5,8,43,5,7,2], 1)
[0, 4, 6, 7, 8]
I am trying to get the results to be [1, 5, 43, 5, 7]
You're iterating over the range of the index. Iterate over the list instead.
for i in myList:
#check if index is greater than 5
if i >5:
#if the number is greater than 5, add to greaterList
greaterList.append(i)
So, your code gets rewritten as (with some minor changes)
def splitList(myList, option):
final_list = []
if int(option) == 0:
for i in myList:
if i > 5:
final_list.append(i)
elif int(option) == 1:
for i in myList:
if i%2 != 0:
final_list.append(i)
return final_list
You could reduce it by doing
def splitList(myList, option):
if int(option) == 0:
return [elem for elem in myList if elem > 5]
elif int(option) == 1:
return [elem for elem in myList if elem % 2 != 0]
Output -
>>> splitList([1,2,6,4,5,8,43,5,7,2], 1)
[1, 5, 43, 5, 7]
List comprehensions greatly simplify your code.
def split_list(xs, option):
if option:
return [x for x in xs if x % 2]
else:
return [x for x in xs if x > 5]
if ((myList[i])>5):
#if the number is greater than 5, add to greaterList
greaterList.append(i)
Instead of adding the index i, add the value (myList[i]):
if ((myList[i])>5):
#if the number is greater than 5, add to greaterList
greaterList.append(myList[i])
Same thing for the oddList case.
Note: #Sukrit Kalra's solution is preferable, but I'm leaving this up to show that there's multiple ways of solving this.
Take a closer look at your .append() commands... in your compare you're using:
if ((mylList[i])%2!=0)
or
if ((myList[i])>5)
...but when you put it into the list, you're just using
greaterList.append(i)
instead of
greaterList.append(myList[i])
This must be a homework or class somewhere?