Counter for a list adding up to 10 - python-2.7

I'm currently stuck on a question regarding lists and formulating codes. I have to
For example, if list = [4,6] I would have to return 2. (4+6) and (6+4). This code has to work for any length of list and no two numbers will be the same within the list. I'm new to lists and and stuck on how to begin coding.
def countsum(list):
Would appreciate the help

def count_list_aux(num_possibilities, a_list, i, j):
if i == j: # Only 1 item to check now.
if a_list[i] == 10: # The item itself is 10 so that can be a combo.
return num_possibilities + 1
else: # Otherwise we are done.
return num_possibilities
else:
combo = a_list[i] + a_list[j]
if combo == 10: # (4,6) for instance.
return count_list_aux(num_possibilities+2, a_list, i+1, j-1)
elif combo > 10: # (4,8) for instance. Clearly 8 needs to go when we have a sorted list.
return count_list_aux(num_possibilities, a_list, i, j-1)
else: # (4,7) for instance. Clearly 4 needs to go when we have a sorted list.
return count_list_aux(num_possibilities, a_list, i+1, j)
def countsum(a_list):
a_list = sorted(a_list)
return count_list_aux(0, a_list, 0, len(a_list)-1)
print(countsum([4,6,3,7,5,2,8]))
I have made a recursive solution where I simply sort the list (ascending order) and then recursively add up left most (i) and right most (j) and check if they add up to 10. If they do, then I increment num_possibiltiies by 2 (eg. 6,4 and 4,6 are 2 combos). If the sum is greater than 10, then I decrement j by 1 because clearly, the current index j cannot work with any other values in the list (list is sorted). Similarly, if the sum is smaller than 10, I increment i by 1 as the current index i cannot work with any other values to get a sum of 10 (it failed with the largest value at index j).

The function can also be implemented using:
from itertools import combinations
from math import factorial
def countsum(L):
x = 10
n = 2
return sum(factorial(n) for c in combinations(L, n) if sum(c) == x)
The factorial is because combinations produces tuples that are sets of items, rather than counting each of the permutations, simply compute their count. As the factorial depends on a constant it can be hoisted:
def countsum(L):
x = 10
n = 2
return factorial(n) * sum(1 for c in combinations(L, n) if sum(c) == x)

Related

Python Subsequence

Example: I have the array[9,0,1,2,3,6,4,5,0,9,7,8,9] and It should return the max consecutive subsequence, so the answer should be (and if the number is 9 and the next one is 0 than it's fine) 9,0,1,2,3, but my code is returning 0,1,2,3
Starting from each element, do a loop that compares adjacent elements, until you get a pair that isn't consecutive.
Instead of saving all the consecutive sublists in another list, just save the sublist in a variable. When you get another sublist, check if it's longer and replace it.
def constructPrintLIS(arr: list, n: int):
longest_seq = []
for i in range(n-1):
for j in range(i, n-1):
if not (arr[j] == arr[j+1]-1 or (arr[j] == 9 and arr[j+1] == 0)):
break
else:
# if we reach the end, need to update j
j = n
if j - i > len(longest_seq):
longest_seq = arr[i:j+1]
if n - i <= len(longest_seq):
# there can't be any longer sequences, so stop
break
printLIS(longest_seq)

Automatically created list from printed objects

I'm new to Python and am learning via edX and trying to solve ProjectEuler math problems. The second problem is about summing all even Fibonacci numbers that are less than 4,000,000. I was able to solve this problem with Python, but not in a way that was satisfying to me.
First I defined a fib function:
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
Then, I was able to print all even Fibonacci numbers with value less than 4,000,000:
n = 0
while True:
if fib(n) < 40000000 and fib(n) % 2 == 0:
print(fib(n))
n = n+1
elif fib(n) < 4000000 and fib(n) % 2 != 0:
n = n+1
else:
break
Then, I manually formed a list from what was printed and summed the list. The problem is that I don't want to have to do that. I want the computer to form the list as it goes and then sums up the value. Anyone know how I can do that? Thanks!
You could write a generator that produces fib numbers, then just take from it while the numbers are less than 4 million (4e6):
import itertools
def fib(n):
if n == 0: return 0
elif n == 1: return 1
else: return fib(n-1) + fib(n-2)
# A generator function that lazily produces new fib numbers
def gen_fibs():
n = 1
while True:
yield fib(n)
n += 1
# Take from the generator while n is less than 4 million
fibs = itertools.takewhile(lambda n: n <= 4e6, gen_fibs())
# Keep all the evens
even_fibs = (n for n in fibs if n % 2 == 0)
# Then print the sum of even fibs
print(sum(even_fibs))
There may be a way to get around defining the generator manually, but this is still fairly neat. If range had a 0-arity version that produced an infinite list, I could have reduced the first part down to a generator expression instead, but such is life.

Python's faster alternative to lists for prime numbers?

I need to find the first pair of primes within specified range, these primes must be a certain difference from each other and have no other primes within that difference.
My code seems to be working, but it is painfully slow - I presume because of my use of lists to handle primes. What would be a better approach?
g=difference;
n=first number in range
m= second number in range
def gap(g,n,m):
prime_list = []
for num in range(n,m+1):
if all(num%i!=0 for i in range(2,int(num**0.5)+1)):
prime_list.append(num)
if len(prime_list)<1:
return None
for pnum in prime_list:
for index in range(len(prime_list)):
pnum2 = prime_list[index]
diff = abs(pnum - pnum2)
if diff == g:
checker = abs(prime_list.index(pnum2) - prime_list.index(pnum))
if checker <=1:
return [pnum, pnum2]
Some tests:
Test.assert_equals(gap(2,100,110), [101, 103])
Test.assert_equals(gap(4,100,110), [103, 107])
Test.assert_equals(gap(2, 10000000, 11000000), [10000139, 10000141])
Why store the primes in a list at all? You only need to remember one at a time. You'll be working through them in ascending order and, as jasonharper points out, all you need to do is stop when you encounter the first delta equal to g between successive primes:
def gap(g, n, m):
previous_prime = None
for candidate in range(n, m + 1):
if all(candidate % factor for factor in range(2, int(candidate ** 0.5) + 1)):
if previous_prime is not None and candidate - previous_prime == g:
return [previous_prime, candidate]
previous_prime = candidate

How to find all bitmask combinations given i subsequent values can be "0", j can be "1"?

Input.
I have a bit array sized n and two integers, 1<=i<=n and 0<=j<=n.
i indicates the maximum of subsequent numbers that can be 0. j indicates the maximum of subsequent numbers that can be 1.
Desired Output
I search for a method that returns all possible bit arrays sized n that fulfill these constraints.
Just looping through all array combinations (first without constraints) would result in exponential time. (Especially if i/j>>1. I suppose you can do better).
How can I effectively find those bitmask combinations?
Example
Input: i = 1, j = 2, n = 3
Result: Possible arrays are [0,1,0], [1,0,1],[1,1,0],[0,1,1].
This is nice problem for dynamic programming solution. It is enough to have method that returns number of strings starting with given digit (0 or 1) with given length. Than number of digits of length n is sum of strings starting with 0 and starting with 1.
Simple python solution with memoization is:
_c = {} # Cache
def C(d, n, ij):
if n <= 1:
return 1
if (d, n) not in _c:
_c[(d, n)] = sum(C(1-d, n-x, ij) for x in xrange(1, min(ij[d], n)+1))
return _c[(d, n)]
def B(n, i, j):
ij = [i, j] # Easier to index
_c.clear() # Clears cache
return C(0, n, ij) + C(1, n, ij)
print B(3, 1, 2)
print B(300, 10, 20)
Result is:
4
1896835555769011113367758506440713303464223490691007178590554687025004528364990337945924158
Since value for given digit and length depends on values of opposite digit and length less than given length, solution can be also obtained by calculating values increasingly by length. Python solution:
def D(n, i, j):
c0 = [1] # Initialize arrays
c1 = [1]
for x in xrange(1, n+1): # For each next digit calculate value
c0.append(sum(c1[x-y] for y in xrange(1, min(i, x)+1)))
c1.append(sum(c0[x-y] for y in xrange(1, min(j, x)+1)))
return c0[-1] + c1[-1] # Sum strings starting of length n with 0 and 1
print D(3, 1, 2)
print D(300, 10, 20)
Later approach is easier to implement in C++.

Python implementation for next_permutation in STL

next_permutation is a C++ function which gives the lexicographically next permutation of a string. Details about its implementation can be obtained from this really awesome post. http://wordaligned.org/articles/next-permutation
Is anyone aware of a similar implementation in Python?
Is there a direct python equivalent for STL iterators?
itertools.permutations is close; the biggest difference is it treats all items as unique rather than comparing them. It also doesn't modify the sequence in-place. Implementing std::next_permutation in Python could be a good exercise for you (use indexing on a list rather than random access iterators).
No. Python iterators are comparable to input iterators, which are an STL category, but only the tip of that iceberg. You must instead use other constructs, such as a callable for an output iterator. This breaks the nice syntax generality of C++ iterators.
Here's a straightforward Python 3 implementation of wikipedia's algorithm for generating permutations in lexicographic order:
def next_permutation(a):
"""Generate the lexicographically next permutation inplace.
https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
Return false if there is no next permutation.
"""
# Find the largest index i such that a[i] < a[i + 1]. If no such
# index exists, the permutation is the last permutation
for i in reversed(range(len(a) - 1)):
if a[i] < a[i + 1]:
break # found
else: # no break: not found
return False # no next permutation
# Find the largest index j greater than i such that a[i] < a[j]
j = next(j for j in reversed(range(i + 1, len(a))) if a[i] < a[j])
# Swap the value of a[i] with that of a[j]
a[i], a[j] = a[j], a[i]
# Reverse sequence from a[i + 1] up to and including the final element a[n]
a[i + 1:] = reversed(a[i + 1:])
return True
It produces the same results as std::next_permutation() in C++ except it doesn't transforms the input into the lexicographically first permutation if there are no more permutations.
itertools is seems to be what you need.
An implementation for the lexicographic-ally next permutation in Python (reference)
def lexicographically_next_permutation(a):
"""
Generates the lexicographically next permutation.
Input: a permutation, called "a". This method modifies
"a" in place. Returns True if we could generate a next
permutation. Returns False if it was the last permutation
lexicographically.
"""
i = len(a) - 2
while not (i < 0 or a[i] < a[i+1]):
i -= 1
if i < 0:
return False
# else
j = len(a) - 1
while not (a[j] > a[i]):
j -= 1
a[i], a[j] = a[j], a[i] # swap
a[i+1:] = reversed(a[i+1:]) # reverse elements from position i+1 till the end of the sequence
return True
A verbose implementation of this approach on lexicographic ordering
def next_permutation(case):
for index in range(1,len(case)):
Px_index = len(case) - 1 - index
#Start travelling from the end of the Data Structure
Px = case[-index-1]
Px_1 = case[-index]
#Search for a pair where latter the is greater than prior
if Px < Px_1 :
suffix = case[-index:]
pivot = Px
minimum_greater_than_pivot_suffix_index = -1
suffix_index=0
#Find the index inside the suffix where ::: [minimum value is greater than the pivot]
for Py in suffix:
if pivot < Py:
if minimum_greater_than_pivot_suffix_index == -1 or suffix[minimum_greater_than_pivot_suffix_index] >= Py:
minimum_greater_than_pivot_suffix_index=suffix_index
suffix_index +=1
#index in the main array
minimum_greater_than_pivot_index = minimum_greater_than_pivot_suffix_index + Px_index +1
#SWAP
temp = case[minimum_greater_than_pivot_index]
case[minimum_greater_than_pivot_index] = case[Px_index]
case[Px_index] = temp
#Sort suffix
new_suffix = case[Px_index+1:]
new_suffix.sort()
#Build final Version
new_prefix = case[:Px_index+1]
next_permutation = new_prefix + new_suffix
return next_permutation
elif index == (len(case) -1):
#This means that this is at the highest possible lexicographic order
return False
#EXAMPLE EXECUTIONS
print("===INT===")
#INT LIST
case = [0, 1, 2, 5, 3, 3, 0]
print(case)
print(next_permutation(case))
print("===CHAR===")
#STRING
case_char = list("dkhc")
case = [ord(c) for c in case_char]
print(case)
case = next_permutation(case)
print(case)
case_char = [str(chr(c)) for c in case]
print(case_char)
print(''.join(case_char))
The algorithm is implemented in module more_itertools as part of function more_itertools.distinct_permutations:
Documentation;
Source code.
def next_permutation(A):
# Find the largest index i such that A[i] < A[i + 1]
for i in range(size - 2, -1, -1):
if A[i] < A[i + 1]:
break
# If no such index exists, this permutation is the last one
else:
return
# Find the largest index j greater than j such that A[i] < A[j]
for j in range(size - 1, i, -1):
if A[i] < A[j]:
break
# Swap the value of A[i] with that of A[j], then reverse the
# sequence from A[i + 1] to form the new permutation
A[i], A[j] = A[j], A[i]
A[i + 1 :] = A[: i - size : -1] # A[i + 1:][::-1]
Alternatively, if the sequence is guaranteed to contain only distinct elements, then next_permutation can be implemented using functions from module more_itertools:
import more_itertools
# raises IndexError if s is already the last permutation
def next_permutation(s):
seq = sorted(s)
n = more_itertools.permutation_index(s, seq)
return more_itertools.nth_permutation(seq, len(seq), n+1)