I'm new to Python and have just started to try out LeetCode to build my chops. On this classic question my code misses a test case.
The problem is as follows:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
I miss on test case [3,2,4] with the target number of 6, which should return the indices of [1,2], but hit on test case [1,5,7] with the target number of 6 (which of course returns indices [0,1]), so it appears that something is wrong in my while loop, but I'm not quite sure what.
class Solution:
def twoSum(self, nums, target):
x = 0
y = len(nums) - 1
while x < y:
if nums[x] + nums[y] == target:
return (x, y)
if nums[x] + nums[y] < target:
x += 1
else:
y -= 1
self.x = x
self.y = y
self.array = array
return None
test_case = Solution()
array = [1, 5, 7]
print(test_case.twoSum(array, 6))
Output returns null on test case [3,2,4] with target 6, so indices 1 and 2 aren't even being summarized, could I be assigning y wrong?
A brute force solution is to double nest a loop over the list where the inner loop only looks at index greater than what the outer loop is currently on.
class Solution:
def twoSum(self, nums, target):
for i, a in enumerate(nums, start=0):
for j, b in enumerate(nums[i+1:], start=0):
if a+b==target:
return [i, j+i+1]
test_case = Solution()
array = [3, 2, 4]
print(test_case.twoSum(array, 6))
array = [1, 5, 7]
print(test_case.twoSum(array, 6))
array = [2, 7, 11, 15]
print(test_case.twoSum(array, 9))
Output:
[1, 2]
[0, 1]
[0, 1]
Bit different approach. We will build a dictionary of values as we need them, which is keyed by the values we are looking for.If we look for a value we track the index of that value when it first appears. As soon as you find the values that satisfy the problem you are done. The time on this is also O(N)
class Solution:
def twoSum(self, nums, target):
look_for = {}
for n,x in enumerate(nums):
try:
return look_for[x], n
except KeyError:
look_for.setdefault(target - x,n)
test_case = Solution()
array = [1, 5, 7]
array2 = [3,2,4]
given_nums=[2,7,11,15]
print(test_case.twoSum(array, 6))
print(test_case.twoSum(array2, 6))
print(test_case.twoSum(given_nums,9))
output:
(0, 1)
(1, 2)
(0, 1)
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
ls=[]
l2=[]
for i in nums:
ls.append(target-i)
for i in range(len(ls)):
if ls[i] in nums :
if i!= nums.index(ls[i]):
l2.append([i,nums.index(ls[i])])
return l2[0]
x= Solution()
x.twoSum([-1,-2,-3,-4,-5],-8)
output
[2, 4]
import itertools
class Solution:
def twoSum(self, nums, target):
subsets = []
for L in range(0, len(nums)+1):
for subset in itertools.combinations(nums, L):
if len(subset)!=0:
subsets.append(subset)
print(subsets) #returns all the posible combinations as tuples, note not permutations!
#sums all the tuples
sums = [sum(tup) for tup in subsets]
indexes = []
#Checks sum of all the posible combinations
if target in sums:
i = sums.index(target)
matching_combination = subsets[i] #gets the option
for number in matching_combination:
indexes.append(nums.index(number))
return indexes
else:
return None
test_case = Solution()
array = [1,2,3]
print(test_case.twoSum(array, 4))
I was trying your example for my own learning. I am happy with what I found. I used the itertools to make all the combination of the numbers for me. Then I used list manipulation to sum all the possible combination of numbers in your input array, then I just check in one shot if the target is inside the sum array or not. If not then return None, return the indexes otherwise. Please note that this approach will return all the three indexes as well, if they add up to the target. Sorry it took so long :)
This one is more comprehensive cohesive efficient one even so shorter lines of code.
nums = [6, 7, 11, 15, 3, 6, 5, 3,99,5,4,7,2]
target = 27
n = 0
for i in range(len(nums)):
n+=1
if n == len(nums):
n == len(nums)
else:
if nums[i]+nums[n] == target:
# to find the target position
print([nums.index(nums[i]),nums.index(nums[n])])
# to get the actual numbers to add print([nums[i],nums[n]])
Related
I have a list of decimal numbers. How can I query between which two values a value falls closest to, giving breakpoints?
my list=[1,2,3,4,5,6,7....,999] and value=54,923 which python code returns value between 54 and 55? Also giving the closest Values: (54,55)
Here's a way which should be more efficient than a for loop:
from bisect import bisect_right
# value = 54.923
# my_list = [1, 2, 3, ... 999]
# right = the index of the first number in my_list that is larger than value
right = bisect_right(my_list, value)
# Case where value is in my_list
if my_list[right - 1] == value:
bounds = [my_list[right - 1]]
# No lower bound or upper bound
elif right == 0:
bounds = ["No lower bound", my_list[right]]
elif right == len(my_list):
bounds = [my_list[right - 1], "No upper bound"]
# value is in between 2 values in my_list
else:
bounds = [my_list[right - 1], my_list[right]]
The output is [54, 55].
Given a list of integers sorted in ascending order and trying to find values either side of some other value you could do this:
list_ = [i for i in range(100)]
def find_nearest(list_, n):
for x, y in zip(list_, list_[1:]):
if x == n:
return n, n
if y > n:
return x, y
print(find_nearest(list_, 42.5))
Output:
(42, 43)
You might need to change the logic for the case where n is equal to an entry in the list. What values would you return then?
A simple iteration:
def query(lst, target):
if target < lst[0] or target > lst[-1]:
# Target is out of list
return None
for i in range(len(lst)):
if lst[i] > target:
return [lst[i-1], lst[i]]
return None
>>> query([1, 2, 3], 2.5)
[2, 3]
If your list is always in the form [1,2,3,4 ... n], and the target is a non-whole decimal:
This is the quickest method:
from math import ceil, floor
def query(target):
"""Lst must be a list of sequential integers"""
return [floor(target), ceil(target)]
>>> query(2.5)
[2, 3]
For checking if the value is in the list as well:
def query(lst, target):
if target < lst[0] or target > lst[-1]:
# Target is out of list
return None
for i in range(len(lst)):
if lst[i] == target:
return [target]
if lst[i] > target:
return [lst[i-1], lst[i]]
return None
Given a list of unsorted integers and a target integer, find out if any pair's difference in the list is equal to the target integer with recursion.
>>> aList = [5, 4, 8, -3, 6]
>>> target = 9
return True
>>> aList = [-1, 5, 4]
>>> target = 3
return False
For and while loops are not allowed.
No imports allowed.
.sort() is not allowed.
I tried this and it didn't work.
def calculate(aList, target):
if len(aList) == 0 and diff != 0:
return False
startIndex = 0
endIndex = len(aList) - 1
return resursive_sum(aList, target, startIndex, endIndex)
def resursive_sum(aList, targ, start, end):
print(f'Start: {start}')
print(f'End: {end}')
if start == end:
return False
elif aList[end] - aList[start] == targ:
return True
elif aList[end] - aList[start] < targ:
return resursive_sum(values, targ, start, end - 1)
return resursive_sum(aList, targ, start + 1, end)
I'm unsure of how this problem could be solved if we aren't able to use loops to sort the list. Even if we could use recursion to sort the list, how should the recursion look so that it can scan every pair's difference?
So I actually implemented it, but for educational purposes I'm not gonna post it until a bit later (I'll update it in a few hours) as I assume this is for a class or some other setting where you should figure it out on your own.
Assume you are trying to hit a difference target t = 5 and you are evaluating an arbitrary element 8. There are only two values that would allow 8 to have a complement in the set: 8 + 5 = 13 and 8 - 5 = 3.
If 3 or 13 had been in any previous elements, you would know that the set has a pair of complements. Otherwise, you'd want to record the fact that 8 had been seen. Thereby, if 3 was found later, 8 would be queried as 3 + 5 = 8 would be considered.
In other words, I am proposing a method where you recursively traverse the list and either
(base case) Are at the end of the list
Have a current element a such that a + t or a - t has been seen
Record that the current element has been seen and go to the next element
Ideally, this should have O(n) time complexity and O(n) space complexity in the worst case (assuming efficient implementation with pass-by-reference or similar, and also amortized constant-time set query). It can also be implemented using a basic array, but I'm not going to say that's better (in python).
I'll post my solution in a few hours. Good luck!
EDIT 1: Hopefully, you had enough time to get it to work. The method I described can be done as follows:
def hasDiffRecur(L, t, i, C):
"""
Recursive version to see if list has difference
:param L: List to be considered
:param t: Target difference
:param i: Current index to consider
:param C: Cache set
"""
# We've reached the end. Give up
if i >= len(L):
return False
print(f" > L[{i}] = {L[i]:2}; is {L[i]-t:3} or {L[i]+t:2} in {C}")
# Has the complement been cached?
if L[i] - t in C:
print(f"! Difference between {L[i]} and {L[i]-t} is {t}")
return True
if L[i] + t in C:
print(f"! Difference between {L[i]} and {L[i]+t} is {t}")
return True
# Complement not seen yet. Cache element and go to next element
C.add(L[i])
return hasDiffRecur(L, t, i+1, C)
###################################################################
def hasDiff(L, t):
"""
Initialized call for hasDiffRecur. Also prints intro message.
See hasDiffRecur for param info
"""
print(f"\nIs a difference of {t} present in {L}?")
return hasDiffRecur(L, t, 0, set())
###################################################################
hasDiff([5, 4, 8, -3, 6], 9)
hasDiff([-1, 5, 4], 3)
hasDiff([-1, 5, 4, -1, 7], 0) # If concerned about set non-duplicity
OUTPUT:
Is a difference of 9 present in [5, 4, 8, -3, 6]?
> L[0] = 5; is -4 or 14 in set()
> L[1] = 4; is -5 or 13 in {5}
> L[2] = 8; is -1 or 17 in {4, 5}
> L[3] = -3; is -12 or 6 in {8, 4, 5}
> L[4] = 6; is -3 or 15 in {8, -3, 4, 5}
! Difference between 6 and -3 is 9
Is a difference of 3 present in [-1, 5, 4]?
> L[0] = -1; is -4 or 2 in set()
> L[1] = 5; is 2 or 8 in {-1}
> L[2] = 4; is 1 or 7 in {5, -1}
Is a difference of 0 present in [-1, 5, 4, -1, 7]?
> L[0] = -1; is -1 or -1 in set()
> L[1] = 5; is 5 or 5 in {-1}
> L[2] = 4; is 4 or 4 in {5, -1}
> L[3] = -1; is -1 or -1 in {4, 5, -1}
! Difference between -1 and -1 is 0
EDIT 2:
This is a pretty clever and efficient solution. I do realize that maybe it is the intention to not allow any traversal at all (i.e. no existance querying for set). If that is the case, the above approach can be done with a constant-size list that is pre-allocated to size equal to the range of the values of the list.
If the notion of pre-allocating to the size of the range of the list is still too much iteration, I can think of the exhaustive approach implemented recursively. There is likely a more efficient approach for this, but you could boil the problem down to a double-for-loop-like problem (O(n^2) time complexity). This is a trivial algorithm and I think you can understand it without documentation, so I'll just throw it in there to be complete:
def hasDiffRecur(L, t, i = 0, j = 1):
if i >= len(L): return False
if j >= len(L): return hasDiffRecur(L, t, i+1, i+2)
if abs(L[i] - L[j]) == t: return True
return hasDiffRecur(L, t, i, j+1)
###################################################################
print(hasDiffRecur([5, 4, 8, -3, 6], 9)) # True
print(hasDiffRecur([-1, 5, 4], 3)) # False
print(hasDiffRecur([-1, 5, 4, -1, 7], 0)) # True
choose
I'll start with a generic function that takes a list, t, and a number of elements to choose, n -
def choose(t, n):
if n == 0:
return [[]]
elif not t:
return []
else:
return append \
( map \
( choose(rest(t), n - 1)
, lambda c: append([first(t)], c)
)
, choose(rest(t), n)
)
print(choose(["a", "b", "c", "d"], 2))
[['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']]
helpers
Your question imposes quite a few restrictions and Python is a multi-paradigm language and so we're going to use a number of helpers to make things readable
def first(t):
return t[0]
def rest(t):
return t[1:]
def append(t0, t1):
return t0 + t1
I don't know if map counts as an import, but we will define our own just in case -
def map(t, f):
if not t:
return []
else:
return append \
( [f(first(t))]
, map(rest(t), f)
)
solve
Great, now that we've finished implementing choose, let's see how we can apply it to our problem
print(choose([5, 4, 8, -3, 6], 2))
[[5, 4], [5, 8], [5, -3], [5, 6], [4, 8], [4, -3], [4, 6], [8, -3], [8, 6], [-3, 6]]
As you can see, we've found all combinations of 2 elements. We just need to loop through these and check if a pair can be subtracted to reach our target, q -
def solve(t, q):
def check(p):
(x, y) = p
return x - y == q or y - x == q
def loop(c):
if not c:
return False
else:
return check(first(c)) or loop(rest(c))
return loop(choose(t, 2))
print(solve([5, 4, 8, -3, 6], 9))
print(solve([-1, 5, 4], 3))
True
False
allowing for
This is a great exercise to build your recursion skills. Disallowing for is the most challenging restriction to overcome. Here's what it could look like if we could use it -
def choose(t, n):
if n == 0:
yield []
elif not t:
return
else:
for c in choose(t[1:], n - 1):
yield [t[0]] + c
yield from choose(t[1:], n)
def solve(t, q):
for (x,y) in choose(t, 2):
if x - y == q or y - x == q:
return True
return False
print(solve([5, 4, 8, -3, 6], 9))
print(solve([-1, 5, 4], 3))
True
False
This variant has an added advantage that it will stop computing combinations as soon as a solution is found. The first variant must compute all combinations first and then begin iterating through them.
allowing other built-ins
Python built-in functions include map and any and offer us another way to get around the for restriction, but I'm unsure if those are allowed -
def choose(t, n):
if n == 0:
yield []
elif not t:
return
else:
yield from map \
( lambda c: [t[0]] + c
, choose(t[1:], n - 1)
)
yield from choose(t[1:], n)
def solve(t, q):
def check(p):
(x,y) = p
return x - y == q or y - x == q
return any(map(check, choose(t, 2)))
print(solve([5, 4, 8, -3, 6], 9))
print(solve([-1, 5, 4], 3))
True
False
Problem:
given an array of int aList and int target,
check if the difference between each element in aList equals to target
use recursion
do not use .sort()
do not use while and for
do not use import
Example:
>>> aList = [5, 4, 8, -3, 6]
>>> target = 9
return True
>>> aList = [-1, 5, 4]
>>> target = 3
return False
Comparing the differences:
5 4 8 -3 6
-------------------------
5 | X
4 | 1 X
8 | 3 4 X
-3 | 6 7 11 X
6 | 1 2 2 9 X
where X means that there's no difference (same number)
since we find 9 there, so it should return True (target is 9)
Traditional for loops
To solve recursion problem, first try to solve it with traditional for loops:
def compareAll(lst, tgt):
for x in lst: # let's call this x loop
for y in lst: # let's call this y loop
if abs(x-y) == tgt:
return True
return False
print( compareAll([5,4,8,-3,6],9) )
print( compareAll([-1,5,4],3) )
This returns True then False
Recursion
Now we can try using recursion loop. Since we already got the for loop, we can convert it like this:
def compareAll(lst, tgt, x=0, y=0):
if(len(lst)-1 == x and len(lst) == y):
return False
if(len(lst) == x or len(lst) == y):
return compareAll(lst, tgt, x+1, 0)
if(abs(lst[x] - lst[y])==tgt):
return True
return compareAll(lst, tgt, x, y+1)
print( compareAll([5,4,8,-3,6],9) )
print( compareAll([-1,5,4],3) )
How I convert for loop into this:
python's for loop is actually foreach loop in most other languages
so, pure for loop in python will be like:
def compareAll(lst, tgt):
x = 0
while x < len(lst): # let's call this x loop
y = 0
while y < len(lst): # let's call this y loop
if abs(lst[x]-lst[y]) == tgt:
return True
y = y+1
x = x+1
return False
print( compareAll([5,4,8,-3,6],9) )
print( compareAll([-1,5,4],3) )
notice the stopping condition of x loop: when all the array element have been looped
so we add stopping condition here: if(len(lst)-1 == x and len(lst) == y): return False
notice the stopping condition of y loop: when all the array element have been looped
so we add stopping condition here: if(len(lst) == x or len(lst) == y): return compareAll(lst, tgt, x+1, 0)
this stops the current y loop and continue with the x loop
then, we add the actual content of the loop: if(abs(lst[x] - lst[y])==tgt): return True
last, we have to continue the loop: return compareAll(lst, tgt, x, y+1)
The key to convert for loop into recursive loop is just to identify when the loop should end, and when the loop should continue.
This should work and is quite concise:
def q(target, aList, memo=set()):
if len(aList) == 0:
return False
num = aList.pop()
memo.add(num)
if target + num in memo:
return True
return q(target, aList, memo)
q(target=9, aList=[5, 4, 8, -3, 6]) # True
q(target=3, aList=[-1,5,4]) # False
The key insight for me is that a target t and a given number n, the difference d is known. Dict/set/hashmaps are fast at detecting membership, regardless of how many items are added. So... just pop through the list of values and chuck them into a hashmap for later comparison.
The problem can be solved by checking every possible pair of numbers in the list for a solution. If you are allowed to use Python's standard library, then the solution is pretty straight forward.
from itertools import product
def check(xs, target):
return any(map(lambda x: x[0]-x[1] == target, product(xs, xs)))
Breakdown
product(xs, xs) gives the cross product of xs with itself
any(iterable) returns true if any element of iterable is truthy
map(function, iterable) lazily (applies function to every element of iterable)
lambda arg_tuple: expression annonymous function with arguments arg_tuple and returns the result of expression
The return statement in check uses lazy structures so it only does as much work as
is needed, and is space efficient.
Assuming that this is just an exercise in recursion, it probably doesn't preclude a "brute force" approach. You can use the recursion to pair up every value with the remaining ones until you find a matching difference.
For example:
def hasDiff(L,diff,base=None):
if not L: return False # empty list: no match
if base is None: # search with & without first as base
return hasDiff(L[1:],diff,L[0]) or hasDiff(L[1:],diff)
return abs(base-L[0]) == diff or hasDiff(L[1:],diff,base) # match or recurse
print(hasDiff([5, 4, 8, -3, 6],9)) # True
print(hasDiff([-1, 5, 4],3)) # False
When the function recurses with a base value, it merely checks the first item in the remainder of the list and recurses for the other values. When the function recurses without a base value, it tries to find new pairs that don't involve the first item (i.e. in the remainder of the list)
Given an array of random integers
N = [1,...,n]
I need to find min sum of two consecutive values using divide and conquer.
What is not working here but my IQ?
def minSum(array):
if len(array) < 2:
return array[0]+array[1]
if (len(a)%2) != 0:
mid = int(len(array)/2)
leftArray = array[:mid]
rightArray = array[mid+1:]
return min(minSum(leftArray),minSum(rightArray),crossSum(array,mid))
else:
mid = int(len(array)/2)
leftArray = array[:mid]
rightArray = array[mid:]
return min(minSum(leftArray), minSum(rightArray), array[mid]+array[mid+1])
def crossSum(array,mid):
return min(array[mid-1]+array[mid],array[mid]+array[mid+1])
The main problem seems to be that the first condition is wrong: If len(array) < 2, then the following line is bound to raise an IndexError. Also, a is not defined. I assume that that's the name of the array in the outer scope, thus this does not raise an exception but just silently uses the wrong array. Apart from that, the function seems to more-or-less work (did not test it thoroughly, though.
However, you do not really need to check whether the array has odd or even length, you can just use the same code for both cases, making the crossSum function unneccesary. Also, it is kind of confusing that the function for returning the min sum is called maxSum. If you really want a divide-and-conquer approach, try this:
def minSum(array):
if len(array) < 2:
return 10**100
elif len(array) == 2:
return array[0]+array[1]
else:
# len >= 3 -> both halves guaranteed non-empty
mid = len(array) // 2
leftArray = array[:mid]
rightArray = array[mid:]
return min(minSum(leftArray),
minSum(rightArray),
leftArray[-1] + rightArray[0])
import random
lst = [random.randint(1, 10) for _ in range(20)]
r = minSum(lst)
print(lst)
print(r)
Random example output:
[1, 5, 6, 4, 1, 2, 2, 10, 7, 10, 8, 4, 9, 5, 7, 6, 5, 1, 4, 9]
3
However, a simple loop would be much better suited for the problem:
def minSum(array):
return min(array[i-1] + array[i] for i in range(1, len(array)))
I'm new to Python and have just started to try out LeetCode to build my chops. On this classic question my code misses a test case.
The problem is as follows:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
I miss on test case [3,2,4] with the target number of 6, which should return the indices of [1,2], but hit on test case [1,5,7] with the target number of 6 (which of course returns indices [0,1]), so it appears that something is wrong in my while loop, but I'm not quite sure what.
class Solution:
def twoSum(self, nums, target):
x = 0
y = len(nums) - 1
while x < y:
if nums[x] + nums[y] == target:
return (x, y)
if nums[x] + nums[y] < target:
x += 1
else:
y -= 1
self.x = x
self.y = y
self.array = array
return None
test_case = Solution()
array = [1, 5, 7]
print(test_case.twoSum(array, 6))
Output returns null on test case [3,2,4] with target 6, so indices 1 and 2 aren't even being summarized, could I be assigning y wrong?
A brute force solution is to double nest a loop over the list where the inner loop only looks at index greater than what the outer loop is currently on.
class Solution:
def twoSum(self, nums, target):
for i, a in enumerate(nums, start=0):
for j, b in enumerate(nums[i+1:], start=0):
if a+b==target:
return [i, j+i+1]
test_case = Solution()
array = [3, 2, 4]
print(test_case.twoSum(array, 6))
array = [1, 5, 7]
print(test_case.twoSum(array, 6))
array = [2, 7, 11, 15]
print(test_case.twoSum(array, 9))
Output:
[1, 2]
[0, 1]
[0, 1]
Bit different approach. We will build a dictionary of values as we need them, which is keyed by the values we are looking for.If we look for a value we track the index of that value when it first appears. As soon as you find the values that satisfy the problem you are done. The time on this is also O(N)
class Solution:
def twoSum(self, nums, target):
look_for = {}
for n,x in enumerate(nums):
try:
return look_for[x], n
except KeyError:
look_for.setdefault(target - x,n)
test_case = Solution()
array = [1, 5, 7]
array2 = [3,2,4]
given_nums=[2,7,11,15]
print(test_case.twoSum(array, 6))
print(test_case.twoSum(array2, 6))
print(test_case.twoSum(given_nums,9))
output:
(0, 1)
(1, 2)
(0, 1)
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
ls=[]
l2=[]
for i in nums:
ls.append(target-i)
for i in range(len(ls)):
if ls[i] in nums :
if i!= nums.index(ls[i]):
l2.append([i,nums.index(ls[i])])
return l2[0]
x= Solution()
x.twoSum([-1,-2,-3,-4,-5],-8)
output
[2, 4]
import itertools
class Solution:
def twoSum(self, nums, target):
subsets = []
for L in range(0, len(nums)+1):
for subset in itertools.combinations(nums, L):
if len(subset)!=0:
subsets.append(subset)
print(subsets) #returns all the posible combinations as tuples, note not permutations!
#sums all the tuples
sums = [sum(tup) for tup in subsets]
indexes = []
#Checks sum of all the posible combinations
if target in sums:
i = sums.index(target)
matching_combination = subsets[i] #gets the option
for number in matching_combination:
indexes.append(nums.index(number))
return indexes
else:
return None
test_case = Solution()
array = [1,2,3]
print(test_case.twoSum(array, 4))
I was trying your example for my own learning. I am happy with what I found. I used the itertools to make all the combination of the numbers for me. Then I used list manipulation to sum all the possible combination of numbers in your input array, then I just check in one shot if the target is inside the sum array or not. If not then return None, return the indexes otherwise. Please note that this approach will return all the three indexes as well, if they add up to the target. Sorry it took so long :)
This one is more comprehensive cohesive efficient one even so shorter lines of code.
nums = [6, 7, 11, 15, 3, 6, 5, 3,99,5,4,7,2]
target = 27
n = 0
for i in range(len(nums)):
n+=1
if n == len(nums):
n == len(nums)
else:
if nums[i]+nums[n] == target:
# to find the target position
print([nums.index(nums[i]),nums.index(nums[n])])
# to get the actual numbers to add print([nums[i],nums[n]])
I would like to generate a sequence in a list, I know how to do this using a for loop, but if I wanted to generate the list such that the previously generated element was included in the next element, how would I do this? I am very unsure
i.e generate the list such that its items were:
where x is just a symbol
[x,(x)*(x+1),(x)*(x+1)*(x+2)]
rather than [x,x+1,x+2]
Any help greatly appreciated!
I like to use a generator for this sort of thing.
def sequence(x, N):
i = 0
result = 1
while i < N:
result *= (x + i)
i += 1
yield result
>>> list(sequence(5, 10))
[5, 30, 210, 1680, 15120, 151200, 1663200, 19958400, 259459200, 3632428800L]
If you have numpy installed, this is faster:
np.multiply.accumulate(np.arange(x, x + N))
Basically, you need to maintain state between the elements, and the list comprehension won't do that for you. A couple of ways to maintain state that come to mind are, a) use a generator, b) use a class EDIT or c) a closure.
Use a generator
def product(x, n):
accumulator = 1
for i in xrange(n + 1):
accumulator *= x + i
yield accumulator
x = 5
print [n for n in product(x, 2)]
# or just list(product(x, 2))
Or, use a class to maintain state
class Accumulator(object):
def __init__(self):
self.value = 1
self.count = 0
def __call__(self, x):
self.value *= x + self.count
self.count += 1
return self.value
a = Accumulator()
x = 5
print [a(x) for _ in xrange(3)]
...The benefit of the class approach is that you could use a different value for x each iteration, like:
b = Accumulator()
print [b(x) for x in [1, 2, 3]]
>>> [1, 3, 15]
EDIT:
Just to be thorough, a closure would work, too:
def accumulator():
# we need a container here because closures keep variables by reference; could have used a list too
state = {'value': 1, 'count': 0}
def accumulate(x):
state['value'] *= x + state['count']
state['count'] += 1
return state['value']
return accumulate
a = accumulator()
print [a(5) for _ in xrange(3)]
Try this. Deque are used to get a fast access to the elements at the end of the constructing list, as well as a constant append time. pol[-1] means the last element in the queue.
from collections import deque
def multCum(f, x, end):
pol = deque([x])
for i in range(1, end):
pol.append(f(pol[-1],(x+i)))
return list(pol)
def f(x, y):
return x * y
multCum(f, 1, 3)
[1, 2, 6]
Use generators with list comprehensions.
def reqd(x, n):
'''x is the number and n is number of elements '''
yield x
i = 0
original = x
while i < n:
i += 1
x *= (original + i)
yield x
x = 2
listt = [a for a in reqd(x, 10)]
print listt
Change the list comprehension in the end to get the list that you want.
More idiomatic hacking using for-comprehensions and a custom operator:
def n(a):
global previous
previous = a
return a
[n(previous * (x+i)) for previous in [1] for i in range(0,3)]
yields, if x == 1,
[1, 2, 6]
Computationally wasteful but gets the job done
from operator import mul
z = range(5, 11)
print z
[5, 6, 7, 8, 9, 10]
[reduce(mul, z[:i]) for i in range(1, len(z))]
[5, 30, 210, 1680, 15120]