looking for a more elegant solution to this [closed] - python

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
Return the sum of the numbers in the array, except ignore sections of numbers starting with a 6 and extending to the next 7 (every 6 will be followed by at least one 7). Return 0 for no numbers.
sum67([1, 2, 2]) ? 5
sum67([1, 2, 2, 6, 99, 99, 7]) ? 5
sum67([1, 1, 6, 7, 2]) ? 4
def sum67(nums):
dontadd = 0
sum = 0
for i in range(0, len(nums)):
if dontadd == 0:
if nums[i] == 6:
dontadd = 1
else:
sum += nums[i]
else:
if nums[i] == 7:
dontadd = 0
else:
pass# nothing happens. It is useful as a placeholder when a statement is required syntactically
return sum
Looking for a more elegant solution to this problem from codingbat. This answer doesn't seem as intuitive as it could be

If we can just remove the elements that we don't want, then we can use a simple sum. Here is an example:
def sum67(nums):
nums=nums[:]
while 6 in nums:
i=nums.index(6)
j=nums.index(7,i)
del nums[i:j+1]
return sum(nums)
First, we use nums=nums[:] to make a copy. The caller probably isn't expecting nums to change.
nums.index(6) finds the index of the first element that has a value of 6. nums.index(7,i) finds the index of the first element that has a value of 7 after the index i. del nums[i:j+1] then deletes the elements in the range from i to j, including the element at j.

The thing I like most about Python is that it makes it so easy to break a problem apart.
def skip67(seq):
skipping = False
for value in seq:
skipping = skipping or value == 6
yield 0 if skipping else value
skipping = skipping and value != 7
def sum67(seq):
return sum(skip67(seq))
>>> sum67([1, 2, 2])
5
>>> sum67([1, 2, 2, 6, 99, 99, 7])
5
>>> sum67([1, 1, 6, 7, 2])
4

This isn't too bad (you might argue it's trying to be too clever though).
>>> def sum67(nums):
... while 6 in nums:
... index = nums.index(6)
... while nums.pop(index) != 7:
... pass
... return sum(nums)
...
>>> sum67([1, 2, 3])
6
>>> sum67([1, 2, 2, 6, 99, 99, 7])
5
>>> sum67([1, 1, 6, 7, 2])
4
>>> sum67([1, 2, 2, 6, 99, 99, 7, 8, 1, 6, 0, -1000, 7, 2])
16
Here's a really goofy one(will not work with negative numbers)
>>> import re
>>> def sum67(nums):
... return sum(int(j) for j in re.sub(r'6\d*?7', '', ''.join((str(i) for i in nums))))
>>> sum67([1, 2, 3])
6
>>> sum67([1, 2, 2, 6, 99, 99, 7])
5
>>> sum67([1, 2, 2, 6, 99, 99, 7, 8, 1, 6, 0, 7, 2])
16
Please don't ever write code like that :p
One more awful one liner before I leave this alone:
>>> def sum67(nums):
... return sum(i if i != 6 else -sum(nums[pos+1:nums.index(7,pos)+1]) for pos, i in enumerate(nums))
...
>>> sum67([1, 2, 2, 6, 99, 99, 7])
5
>>> sum67([1, 2, 2, 6, 99, 99, 7, 8, 1, 6, 0, -1000, 7, 2])
16

def sum67(nums):
i=0
sum=0
n=len(nums)
while i<n:
if nums[i]==6:
i=nums.index(7,i)
else:
sum += nums[i]
i+=1
return sum

def sum67(L):
it = iter(L)
return sum(all(i!=7 for i in it) if i == 6 else i for i in it)
A slightly more readable version if you're interested in how this works:
def slice67(L):
it = iter(L)
for i in it:
if i != 6:
yield i
else:
while next(it, 7) != 7:
pass
print sum(slice67([1, 2, 2]))

This version does not modify the list.
def sum67(xs):
xs = iter(xs)
s = 0
for x in xs:
if x == 6:
while x != 7:
x = xs.next()
else:
s += x
return s

My solution wouldn't be too different from the OP, but in general I like the idea of always having the add operation there and just having logic to switch the value of "accum" between 1 and 0.
def sum67(nbrs):
total = 0
accum = 1
for nbr in nbrs:
if nbr==6:
accum=0
total += nbr*accum
if accum==0 and nbr==7:
accum=1
return total

Here is a version that may be simpler to understand:
def sum67(nums):
found6 = False
result = 0
for n in nums:
if n==6:
found6 = True
continue
if n==7 and found6:
found6 = False
continue
if not found6:
result += n
return result

How about this?
>>> def sum67(l):
... sum = 0
... add = True
... for i in l:
... add = add and (i != 6)
... sum += add and i or 0
... add = add or i == 7
... return sum
...
>>> print sum67([1, 2, 3])
6
>>> print sum67([1, 2, 2, 6, 99, 99, 7])
5
>>> print sum67([1, 1, 6, 7, 2])
4
>>> print sum67([1, 2, 2, 6, 99, 99, 7, 8, 1, 6, 0, -1000, 7, 2])
16
It takes advantage of the fact that Python evaluates Boolean expressions to the value of first operand that determines the result, e.g., in sum += add and i or 0, if add is False, it enters the or part and evaluates to 0, if add were True, it would evaluate to i.

def sum67(nums):
while 6 in nums:
for x in nums[nums.index(6):]:
nums.remove(x)
if x == 7:
break
return sum(nums)

A one-liner with list comprehension:
def sum67(nums):
return sum([x for index, x in enumerate(nums) if (((nums[(index - nums[index::-1].index(6)):].index(7) + (index - nums[index::-1].index(6))) < index) if (6 in nums[:index+1]) else True)])

Related

Scenario if in input numbers are repeat

Code:
n = int(input("Type n: "))
def some_function(n):
numbers, numbers_sum = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], 45
while True:
digit = n % 10
n //= 10
if digit in numbers:
numbers.remove(digit)
numbers_sum -= digit
else:
break
return numbers_sum
print(some_function(n))
Program needs to print the sum of numbers that are not found in the input.
I covered the scenario when numbers are not repeating and for this scenario if the input is 234567890 output is 1 .
But don't have an idea for scenario when numbers are repeating.Etc. if the input is 22334567890 or 223344556677889900 output still needs to be 1 but it's not.
P.S.
I can't do it with strings.
I know 0 doesn't make difference because we are doing with - and +.
the easier way to do it is to transform it to a string and do set operations
>>> n=22334567890
>>> numbers=set("123456789")
>>> numbers-set(str(n))
{'1'}
>>>
and then transform back to integers
>>> sum(map(int,{'1'}))
1
>>>
if you don't want the string conversion, just make a function that give you the digits of the numbers and do the same
>>> def digits(n): #this is a generator function
if n==0:
yield 0
while n:
n,d = divmod(n,10)
yield d
>>> n=22334567890
>>> numbers=set(range(10))
>>> numbers
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> list(digits(n))
[0, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2]
>>>
>>> numbers - set(digits(n))
{1}
>>> sum({1})
1
>>>
I solved it.Code:
n, finish = int(input("Type n: ")), 0
dig_list, num_list = [], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
def sum(n):
while n > 0:
digit = n % 10
n //= 10
dig_list.append(digit)
for i in range (0, 11):
if i in dig_list:
num_list.remove(i)
return num_list
for e in (sum(n)):
finish += e
print(finish)
Purpose of code.
Explanation:
First, we create 2 lists.
The first one(dig_list) has no elements and there we are gonna put all digits of input(n).
The second list is a list of numbers from 0 to 9(num_list).
Then we put all digits of n in the first list.Then using for loop we go through the first list.If numbers from 0 to 9 are found in the first list we remove them from the second list.
In the end, we save the sum(+) of the remaining elements of the second list to a variable sum.

Write a function sum13(nums)

Write a function sum13(nums) that takes a list of ints nums and returns the sum of the numbers in the list, returning 0 for an empty list. Except the number 13 is very unlucky, so it does not count and numbers that come immediately after a 13 also do not count.
Test Result
print(sum13([1, 2, 2, 1, 13]))
6
print(sum13([13, 2, 2, 1]))
3
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
11(EXPECTED)
13(GOT)
here is my program I don't know why the last test code is not running
def sum13(nums):
"""jdhdjkls"""
if len(nums) == 0:
return 0
for i in range(0, len(nums)):
if nums[i] == 13:
nums[i] = 0
if i+1 < len(nums):
nums[i+1] = 0
return sum(nums)
You can use the built-in zip() method to zip two lists skewed like:
[1, 2, 3, 4]
[1, 2, 3, 4]
to
[1, 2, 3, 4]
[2, 3, 4, None]
and check to see if any of the pairs have 13 in them.
Here is how:
def sum13(nums):
s = 0 if nums[0] == 13 else nums[0]
for p in zip(nums, nums[1:]):
if all(n != 13 for n in p):
s += p[1]
return s
print(sum13([1, 2, 2, 1, 13]))
print(sum13([13, 2, 2, 1]))
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
Output:
6
3
11
You can also unpack the pairs:
def sum13(nums):
s = 0 if nums[0] == 13 else nums[0]
for i, j in zip(nums, nums[1:]):
if i != 13 != j:
s += j
return s
print(sum13([1, 2, 2, 1, 13]))
print(sum13([13, 2, 2, 1]))
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
This will solve your problem:
def sum13(nums):
"""jdhdjkls"""
if len(nums) == 0:
return 0
for i in range(0, len(nums)):
if nums[i] == 13:
nums[i] = 0
# problem arises when there are 2 consecutive 13 this if statement will rectify it.
if (i+1 < len(nums)) and (nums[i+1]!=13):
nums[i+1] = 0
return sum(nums)
We could try using recursion to solve this problem:
def sum13(numbers):
if not numbers: # base case
return 0
first, *rest = numbers
if first == 13:
first = 0
if rest and rest[0] != 13:
rest.pop(0)
return first + sum13(rest)
print(sum13([1, 2, 2, 1, 13]))
print(sum13([13, 2, 2, 1]))
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
Though not the style of answer you likely want, we can also coerce itertools.groupby to do the work for us:
from itertools import groupby
def sum13(numbers):
previous13 = False
def is_tainted(number):
nonlocal previous13
tainted = previous13
previous13 = number == 13
return True if tainted else previous13
total = 0
for tainted, subset in groupby(numbers, is_tainted):
if not tainted:
total += sum(subset)
return total
Your scripts can't correspond to 13 13 2 because they are made 0 0 2 in first step.
for and continue is effective for your goal.
def sum13(nums):
sums=0
after13=False
for num in nums:
if num == 13:
after13=True
continue
if not after13:
sums+=num
after13=False
return sums

Python. Replace elements using slice

I need to implement Sieve of Eratosthenes algorithm.
I have list:
bar = [2, 3, 4, 5, 6, 7, 8, 9, 10]
I need to replace each odd element with "0".
Now I have code:
while viewIndex < maxNumber:
bar[viewIndex] = 0
viewIndex += 2
But I remember about slices. And for me it will be nice to write something like this:
bar[currentIndex::2] = 0
But I have error:
TypeError: must assign iterable to extended slice
Maybe you know a beautiful solution to this task.
You should assign the slice to an iterable of the same length as the number of odds:
bar[1::2] = [0]*(len(bar)//2)
print(bar)
# [2, 0, 4, 0, 6, 0, 8, 0, 10]
To extend this for even indices, you need to take into consideration lists with odd-lengths (not relevant for the above case) by adding the modulo 2 value of the list length:
bar[::2] = [0]*(len(bar)//2 + len(bar)%2)
Which is same as:
bar[::2] = [0]*sum(divmod(len(bar), 2))
I use numpy:
foo = np.ones(10)
foo[1::2] = 2
This just works.
You shouldn't have to keep track of indices -- the point of slicing is to make things more convenient, not to force you to keep track of which day of the week relative to the third Tuesday of last month you bought bread.
Use simple for loop
bar = [2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in range(len(bar)):
if bar[i] % 2 != 0:
bar[i] = 0
print(bar)
Output
[2, 0, 4, 0, 6, 0, 8, 0, 10]
You can use map to set elements on odd index to zero,
bar = [2, 3, 4, 5, 6, 7, 8, 9, 10]
print map(lambda i: 0 if bar.index(i)%2!=0 else i, bar)
[2, 0, 4, 0, 6, 0, 8, 0, 10]
or if you want to set odd element value to zero, you can do this,
map(lambda i: 0 if i%2!=0 else i, bar)
Thank to all for answers. My implementation of Sieve of Eatosthenes algorithm:
def resheto(data):
print("\tStart Resheto")
currentIndex = 0
while currentIndex < len(data) - 1:
data[currentIndex + data[currentIndex]::data[currentIndex]] = \
[0] * ((len(data) + 1) // data[currentIndex] - 1)
currentIndex += 1
while currentIndex < len(data) - 1 and data[currentIndex] == 0:
currentIndex += 1
if currentIndex >= len(data) - 1:
break
print("\tEnd Resheto") return data

How to replace K-values of list by skipping 9 from startend

I have a number lets make it a list s = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
and I have k = 4
What I want is to replace 4-values of list s with number 9 which dont have number 9.
means at position 2 ,we have 9,so skip that and replace next one.
Output should be like: [9,9,9,9,9,2,7,3,6,8,4,1,9,0,0,3,6,8]
With this code I am unable to skip 9's in it:
x= [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
k = 4
def elements_replaced(lst, new_element, indices):
return [new_element if i in indices else e for i, e in enumerate(lst)]
output = elements_replaced(x,9,range(k))
print output
you can try:
>>> s = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
>>> k = 4
>>> for index,number in enumerate(s):
if k > 0:
if number != 9:
s[index] = 9
k = k-1
else :
break
>>> s
[9, 9, 9, 9, 9, 2, 7, 3, 6, 8, 4, 1, 9, 0, 0, 3, 6, 8]
You can also use list comprehensions. This will get inefficient if your input list is large relative to the number of nines.
from itertools import chain, repeat
s = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
nines = chain([9] * 4, repeat(None))
result = [x if x == 9 else next(nines) or x for x in s]
print(result)
# [9, 9, 9, 9, 9, 2, 7, 3, 6, 8, 4, 1, 9, 0, 0, 3, 6, 8]
x = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
k = 4
a = 0
while k and a < len(x):
if x[a] != 9:
x[a] = 9
k -= 1
a += 1
x= [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
k = 4
def elements_replaced(lst, new_element, indices):
for index, value in enumerate(lst):
if index in indices and value != new_element:
lst[index] = new_element
return lst
output = elements_replaced(x,9,range(k+1))
print (output)

How do I make my fibonacci sequence go up to n and not over at all

Given the positive integer n create a list consisting of the portion of the Fibonacci sequence less than or equal to n. For example, if n is 6, then the list would be [0, 1, 1, 2, 3, 5] and if n is 1, then the list would be [0, 1, 1].
Currently this is what I have, if n equals numbers as 6 or 20 than the Fibonacci sequence goes over n e.g [0, 1, 1, 2, 3, 5, 8] for n = 6 or [0, 1, 1, 2, 3, 5, 8, 13, 21] for n = 20
this is what I currently have
fib = [0,1]
result = 0
while result < n:
result = fib[-1] + fib[-2]
fib.append(result)
fib = [0,1]
result = fib[-1] + fib[-2]
while result < n:
fib.append(result)
result = fib[-1] + fib[-2]
this should work.
Edit: If you mean you want the last term in your list to be less than n then the below is valid otherwise the answer by saurabh is correct.
What happens if your in the while loops current iteration and your result is above the limit n? You're still going to add it...
Here's a poor man's approach:
fib = [0,1]
result = 0
n = 6
while result < n:
result = fib[-1] + fib[-2]
if (result < n):
fib.append(result)
print(fib)
For 6: [0, 1, 1, 2, 3, 5]
For 20: [0, 1, 1, 2, 3, 5, 8, 13]
Bugs were not using <= and computing new result before appending. This handles all test cases, plus 0 and negative numbers are handled as well:
def fib(n):
if n < 0: # if you care about negative numbers.
return []
fib = [0] # handles n == 0
result = 1 # next result for n > 0
while result <= n: # handles "...less than or equal to n"
fib.append(result)
result = fib[-1] + fib[-2]
return fib
for i in (-1,0,1,6,20):
print(i,fib(i))
Output:
-1 []
0 [0]
1 [0, 1, 1]
6 [0, 1, 1, 2, 3, 5]
20 [0, 1, 1, 2, 3, 5, 8, 13]
Don't forget you can pop as well.
Here's the code:
n = 20
fib = [0, 1]
while fib[-1] <= n:
fib.append(fib[-2] + fib[-1])
fib.pop()
Output:
[0, 1, 1, 2, 3, 5, 8, 13]
Your while condition is set against the last number, you should set it against the total no of elements in your list.
fib = [0,1]
result = 0
count = 20
while len(fib) < count :
result = fib[-1] + fib[-2]
fib.append(result)
print(fib)
print(len(fib))
Will give OP
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
20
you just need to have it print:
fib[-2]
this will print the number that was <= n

Categories

Resources