Write a function sum13(nums) - python

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

Related

Get Indeces of list of numbers Top N, next top N, and last top N

Given that I have a list of numbers:
raw_list = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7,11]
I want to separate it to top N's three times. Which means I want to rank them.
# Top 6 rank as 3
# Next Top 4 rank as 2
# Last Top 1 rank as 1
ranked_list = [3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
What I tried:
sorted(range(len(raw_list)), key=lambda i: raw_list[i])[-2:]
But this only gives indeces of the topmost and not the next topmost value of the list.
Use:
lst = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7, 11]
indices = sorted(range(len(lst)), key=lambda i: lst[i], reverse=True)
ranked_list = [0 for _ in range(len(lst))]
for i, j in enumerate(indices):
if i < 6:
ranked_list[j] = 3
elif i < 6 + 4:
ranked_list[j] = 2
else:
ranked_list[j] = 1
print(ranked_list)
Output
[3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
Here's a different approach which is significantly faster than the accepted answer (if that's important):
Edited to show performance timings between the original and accepted answer because #funnydman wants proof
from timeit import timeit
L = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7, 11]
def func1(list_):
slist = sorted(list_)
result = []
top6 = set(slist[5:])
top4 = set(slist[1:5])
for e in list_:
if e in top6:
result.append(3)
elif e in top4:
result.append(2)
else:
result.append(1)
return result
def func2(list_):
indices = sorted(range(len(list_)), key=lambda i: list_[i], reverse=True)
ranked_list = [0 for _ in range(len(list_))]
for i, j in enumerate(indices):
if i < 6:
ranked_list[j] = 3
elif i < 6 + 4:
ranked_list[j] = 2
else:
ranked_list[j] = 1
return ranked_list
for func in func1, func2:
print(func.__name__, timeit(lambda: func(L)))
Output:
func1 1.3904414890002954
func2 2.388311982000232
IIUC, this will work for you:
import pandas as pd
list(pd.cut(l, bins=[0, 1, 5, 11], labels=[1, 2, 3]))
Output:
[3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]

I need the sum of numbers from a for-loop that is NOT in a list in Python

I'm having a problem returning the sum. I keep getting zero.
I commented the print results for better understanding. Again, my code is returning 0, and not 11.
A = [1, 5, 2, 1, 4, 0]
def solution(A):
start = [i - j for i, j in enumerate(A)]
start.sort() #[-4, -1, 0, 0, 2, 5]
for i in range(0, len(A)):
pair = 0
end = i + A[i] #1, 6, 4, 4, 8, 5
count = bisect_right(start, end) #4, 6, 5, 5, 6, 6
count_1 = count-1 #3, 5, 4, 4, 5, 5
count_2 = count_1 - i #3, 4, 2, 1, 1, 0
pair += count_2 #??????? I need the above added together like this 3+4+2+1+1+0 since
that's the answer.
return pair
print(solution(A))
As you've written in the comments, the last count2 is zero.
You're adding zero to zero, the loop ends, and you return zero.
You need to start the counter outside the loop, or you can sum outside too, like so
counts = []
for i, x in enumerate(A):
counts.append(bisect_right(start, i + x) - 1 - i)
return sum(counts)
Which could be rewritten
return sum(bisect_right(start, i + x) - 1 - i for for i, x in enumerate(A))

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

looking for a more elegant solution to this [closed]

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)])

Categories

Resources