CodingBat sum67: why is this solution wrong?
Question:
I’m working on the following codingbat problem:
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
My solution is:
def sum67(nums):
sum = 0
throwaway = 0
for i in range(len(nums)):
if throwaway == 0:
if nums[i] == 6:
throwaway = 1
elif throwaway == 1 and i > 0 and nums[i-1] == 7:
throwaway = 0
if throwaway == 0:
sum += nums[i]
return sum
I totally know this is not the best solution, but I’m just curious to know why this is wrong. Could you please explain me why this is wrong and in which particular case it gives a wrong result?
Answers:
Well, your program has a bug. Check the results of the following:
print sum67([1,2,5])
print sum67([1,2,6,5,7])
print sum67([1,2,6,5,7,6,7])
This will print:
8
3
16 <-- wrong
If a 7 is followed by a 6 immediately, you will add the 6 and all following numbers. I’m not sure if more than one range of 6 … 7 is allowed in the input, but if it is, you have to fix your algorithm.
This simple implementation does return correct numbers:
def sum67(nums):
state=0
s=0
for n in nums:
if state == 0:
if n == 6:
state=1
else:
s+=n
else:
if n == 7:
state=0
return s
Besides, if you don’t need to use an index for some obscure reasons, you can directly iterate over the elements of a list ( for element in list: ...
).
Here’s my solution to that problem. As answered already, the issue is when a 6 occurs immediately after a 7. I solved this in a slightly different way, so I thought I’d post it.
def sum67(nums):
total = 0
i=0
while i < len(nums):
if nums[i] == 6:
while nums[i] != 7:
i+=1
i+=1
if i<len(nums) and nums[i]!=6:
total+=nums[i]
i+=1
return total
public int sum67(int[] nums) {
int sum=0;
for(int i=0; i<nums.length ; i++)
{
if(nums[i]==6)
for(int k=i+1 ; k<nums.length ; k++ )
{if(nums[k]==7)
{i=k; break;}
}
else if(nums[i]==6)
sum=sum+nums[i];
else
sum=sum+nums[i];
}
return sum;
}
Below is my solution for your reference:
def sum67(nums):
flag=False
sum=0
for num in nums:
if(num==6): #Turn the flag on if the number is 6
flag=True
continue
if(num==7 and flag is True): #Turn the flag Off when 7 is seen after 6
flag=False
continue
if(flag is False): #Keep on adding the nums otherwise
sum+=num
return sum
My solution:
def sum67(nums):
result = 0
flag = True
for num in nums:
if num == 6:
flag = False
if flag:
result += num
if num == 7:
flag = True
return result
I know this isn’t the best solution, but thought to share :
def detect67(nums):
count = nums.count(6)
pos6 = 0
pos7 = 0
sum1 = []
for i in range (len(nums)):
sum1.append(nums[i])
# if I do just sum1 = nums, they use SAME memory locations.
#print ("Count=",count)
for i in range (count):
pos6 = sum1.index(6)
pos7 = sum1.index(7)
if pos7<pos6:
sum1[pos7] = 0
pos7 = sum1.index(7)
del nums[pos6:pos7+1]
del sum1[pos6:pos7+1]
count = nums.count(6)
if count == 0:
return (nums)
return (nums)
def sum67(nums):
detect67(nums)
sums=0
if nums == []:
return 0
for i in range (len(nums)):
sums+=nums[i]
return sums
This is my edit of @TheNeophyte code. I liked that solution because that’s how I’d likely approach the problem. The only edit really was taking out the
if i<len(nums) and nums[i]!=6:
and just putting an elif statement without saying
i<len(nums)
since it’s not needed again after the first while loop.
My edit below VVV
def sum67(anArray):
arrTotal = 0
n =0
while n < len(anArray):
if anArray[n] == 6:
while anArray[n] != 7:
n+=1
n+=1
elif anArray[n] != 6:
arrTotal += anArray[n]
n+=1
return arrTotal
here’s my 6 liner answer. Hope this helps
def summer_67(arr):
s = 0
for x in arr:
if x not in range(6,7+1):
s = s + x
return s
Well, you could use nested loops..
def sum67(nums):
s=0
flag=1
for n in nums:
while flag:
if n!=6:
s+=n
break
else:
flag=0
while not flag:
if n!=9:
break
else:
flag=1
return s
Just to add, if the last element is a 7 you don’t need to iterate through every element. The question states ” ignore sections of numbers starting with a 6 and extending to the next 7 (every 6 will be followed by at least one 7)”. Once you find a 6 you can simply check if the last element is a 7 and if so simply break out and return the sum; otherwise, you can continue to go through the remaining elements. This is helpful when working with a larger number of elements in an array.
ex. [1, 2, 2, 6, 99, 99, 2, 99, 99, 2, 99, 99, 2, 99, 99, 7]
My solution:
def sum67(arr):
sum = 0
tmp = 0
for n in arr:
if n == 6:
tmp = 6
continue
if tmp == 6:
if n == 7:
tmp = 0
continue
elif arr[-1] == 7:
break
else:
continue
sum += n
return sum
My solution for this I Know this is quite readable but not the best code:
def sum67(nums):
offcount = False
sum = 0
for i in range(len(nums)):
if offcount == False:
if nums[i] == 6:
offcount = True
else:
sum = sum + nums[i]
else:
if nums[i] == 7 :
offcount = False
return sum
I hope this helps:)
def sum67(nums):
result = 0
inside = False
for i in range(len(nums)):
if not inside and nums[i] != 6:
result += nums[i]
if nums[i] == 6:
inside = True
if nums[i] == 7:
inside = False
return result
def sum67(nums):
sum = 0
sumbrake = False
for i in nums:
if i != 6 and sumbrake == False:
sum += i
else:
sumbrake = True
if i == 7:
sumbrake= False
return sum
def sum67(nums):
while nums.count(6) >= 1:
list = (nums[0:nums.index(6)]) + (nums[nums.index(7)+1:len(nums)])
nums = list
return sum(nums)
def sum67(arr):
for n in range (0, len(arr)):
if arr[n] == 6:
Sum1 = sum(arr[0:n])
print ("Before 6 Sum Numbers:", Sum1)
for k in range (0, len(arr)):
if arr[k] ==7:
Sum2 = sum(arr[(k)+1:])
print ("After 7 Sum Numbers:", Sum2)
if 6 and 7 in arr:
print("Last Result")
return (Sum1+Sum2)
else:
print("Last Result")
return sum(arr)
simplified code without while and for loop :
def summer_69(arr):
pos6 = 0;
pos9 = 0;
newArr = [];
if 6 in arr:
pos6 = arr.index(6);
if 9 in arr:
pos9 = arr.index(9);
if 6 in arr and 9 in arr :
newArr = arr[0:pos6] + arr[pos9+1:len(arr)];
else:
newArr = arr;
return sum(newArr);
pass
Maybe a more Pythonian approach?
def sum67(arr):
if (6 in arr):
i1 = arr.index(6)
i2 = arr[i1:].index(7)
res = sum(arr[0:i1]+arr[i1+i2+1:])
else:
res = sum(arr)
return res
Here is my 13 line answer, which uses List index positions to exclude values enclosed by every [6..7] pair.
Technique: Return the sum of array elements upon subtracting the (sum of) excluded elements.
def sum67(nums):
idx_list=[]
for i in range(len(nums)):
if nums[i]==6:
c_6 = i # index pos of 6
j = c_6+1 # counter to find index position of 7
while nums[j]!=7: # stop search when 7 spotted in list
j+=1
c_7 = j # index pos of 7
idx_list += list(range(c_6,c_7+1)) # list of index position(s) of elements to be excluded
idx_main = list(set(idx_list)) # set() removes repeated index positions captured while looping
del_val = [nums[i] for i in idx_main]
return sum(nums)-sum(del_val)
def sum67(nums):
sum=0
sum6=0
for n in nums:
sum+=n
if nums.count(6) >= 1:
a=nums.index(6)
b=nums.index(7)+1
nums67=nums[a:b]
for i in nums67:
sum6 += i
return sum - sum6
This may not the best solution , but its simple and gave correct output all cases
def sum67(nums):
sum = 0
i = 0
while( i < len(nums)):
if nums[i] == 6:
while(nums[i] != 7):
i += 1
else:
sum += nums[i]
i += 1
return sum
Just a short and efficient (O(n) time, O(1) space) alternative, using an iterator:
def sum67(nums):
it = iter(nums)
return sum(x for x in it if x != 6 or 7 not in it)
This mainly sums the values. But whenever a 6 is encountered, the 7 not in it
consumes all values until the next 7 (and it’s false, so none of the values from that 6 to that 7 make it into the sum).
def sum67(nums):
c=0
state=True
for i in nums:
if state:
if i==6:
state=False
else:
c+=i
else:
if i==7:
state=True
return c
def sum_69(arr):
x=arr.index(6)
y=arr.index(9)
if 6 not in arr:
return sum(arr)
else:
sum1=arr[:x]
sum2=arr[y+1:]
sum3=sum1+sum2
return sum(sum3)
may be this will help you:
def sum_67(arr):
while 6 in arr:
del arr[arr.index(6):arr.index(7)+1]
return sum(arr)
def sum67(nums):
cnt = 0
ignore = False
for num in nums:
if not ignore and num == 6:
ignore = True
if not ignore:
cnt = cnt + num
if ignore and num == 7:
ignore = False
return cnt
My approach was to build a new list which consisted only of valid segments ie segments that did not start with a 6 and end with a 7 for that corresponding 6. Then I simply computed the sum of the elements of that new list. Worked perfect in the codingbat exercise platform
def sum67(nums):
lst =[] #holds result after discarding invalid segments
while 6 in nums: # Continue until no more 6's found in nums segment
#Find the first 6
idx6 = nums.index(6)
#Build list upto but excluding the first 6
lst += nums[:idx6]
#Find the next 7
idx7 = nums[idx6:].index(7) # this would be relative to nums[idx6:]
#slice
idx = idx6+idx7 # absolute position of 7 w.r.t nums
nums = nums[idx+1:] # slice from the position of the 7 to end
lst += nums # takes care of any leftovers after the last 7
return sum(lst)
Can be condensed to fewer lines of code but I wanted to maintain readability of code. I am wondering if there is a recursive way to solve this. Working on it.
Thanks everyone for your great alternate solutions
Here is the shortest solution I have seen for this question:
def sum67(nums):
while 6 in nums:
del nums[nums.index(6):nums.index(7,nums.index(6))+1]
return sum(nums)
In my solution, I activate and deactivate with a boolean when a 6 starts and a 7 ends. While in the "active == True" state, the code still functions normally except now there’s a "temp_count". If the array reaches a 7, the "temp_count" will be subtracted from "count".
def sum67(nums):
count = 0
temp_count = 0
active = False
for i in range(len(nums)):
count += nums[i]
if nums[i] == 6:
active = True
if nums[i] == 7 and active == True:
active = False
count = count - temp_count - 7
temp_count = 0
if nums[i] == 6 or active == True:
temp_count += nums[i]
return count
The following code works well too.
def sum67(nums):
total1 = 0
total2 = 0
for y in range(0, len(nums)):
if nums[y] == 6:
total1 = nums[0:y]
if nums[y] == 7:
total2 = nums[y + 1:]
total = total1 + total2
return sum(total)
def sum67(nums):
while 6 in nums:
x = nums[nums.index(6):nums.index(7)+1]
for i in x:
nums.remove(i)
return(sum(nums))
I’m working on the following codingbat problem:
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
My solution is:
def sum67(nums):
sum = 0
throwaway = 0
for i in range(len(nums)):
if throwaway == 0:
if nums[i] == 6:
throwaway = 1
elif throwaway == 1 and i > 0 and nums[i-1] == 7:
throwaway = 0
if throwaway == 0:
sum += nums[i]
return sum
I totally know this is not the best solution, but I’m just curious to know why this is wrong. Could you please explain me why this is wrong and in which particular case it gives a wrong result?
Well, your program has a bug. Check the results of the following:
print sum67([1,2,5])
print sum67([1,2,6,5,7])
print sum67([1,2,6,5,7,6,7])
This will print:
8
3
16 <-- wrong
If a 7 is followed by a 6 immediately, you will add the 6 and all following numbers. I’m not sure if more than one range of 6 … 7 is allowed in the input, but if it is, you have to fix your algorithm.
This simple implementation does return correct numbers:
def sum67(nums):
state=0
s=0
for n in nums:
if state == 0:
if n == 6:
state=1
else:
s+=n
else:
if n == 7:
state=0
return s
Besides, if you don’t need to use an index for some obscure reasons, you can directly iterate over the elements of a list ( for element in list: ...
).
Here’s my solution to that problem. As answered already, the issue is when a 6 occurs immediately after a 7. I solved this in a slightly different way, so I thought I’d post it.
def sum67(nums):
total = 0
i=0
while i < len(nums):
if nums[i] == 6:
while nums[i] != 7:
i+=1
i+=1
if i<len(nums) and nums[i]!=6:
total+=nums[i]
i+=1
return total
public int sum67(int[] nums) {
int sum=0;
for(int i=0; i<nums.length ; i++)
{
if(nums[i]==6)
for(int k=i+1 ; k<nums.length ; k++ )
{if(nums[k]==7)
{i=k; break;}
}
else if(nums[i]==6)
sum=sum+nums[i];
else
sum=sum+nums[i];
}
return sum;
}
Below is my solution for your reference:
def sum67(nums):
flag=False
sum=0
for num in nums:
if(num==6): #Turn the flag on if the number is 6
flag=True
continue
if(num==7 and flag is True): #Turn the flag Off when 7 is seen after 6
flag=False
continue
if(flag is False): #Keep on adding the nums otherwise
sum+=num
return sum
My solution:
def sum67(nums):
result = 0
flag = True
for num in nums:
if num == 6:
flag = False
if flag:
result += num
if num == 7:
flag = True
return result
I know this isn’t the best solution, but thought to share :
def detect67(nums):
count = nums.count(6)
pos6 = 0
pos7 = 0
sum1 = []
for i in range (len(nums)):
sum1.append(nums[i])
# if I do just sum1 = nums, they use SAME memory locations.
#print ("Count=",count)
for i in range (count):
pos6 = sum1.index(6)
pos7 = sum1.index(7)
if pos7<pos6:
sum1[pos7] = 0
pos7 = sum1.index(7)
del nums[pos6:pos7+1]
del sum1[pos6:pos7+1]
count = nums.count(6)
if count == 0:
return (nums)
return (nums)
def sum67(nums):
detect67(nums)
sums=0
if nums == []:
return 0
for i in range (len(nums)):
sums+=nums[i]
return sums
This is my edit of @TheNeophyte code. I liked that solution because that’s how I’d likely approach the problem. The only edit really was taking out the
if i<len(nums) and nums[i]!=6:
and just putting an elif statement without saying
i<len(nums)
since it’s not needed again after the first while loop.
My edit below VVV
def sum67(anArray):
arrTotal = 0
n =0
while n < len(anArray):
if anArray[n] == 6:
while anArray[n] != 7:
n+=1
n+=1
elif anArray[n] != 6:
arrTotal += anArray[n]
n+=1
return arrTotal
here’s my 6 liner answer. Hope this helps
def summer_67(arr):
s = 0
for x in arr:
if x not in range(6,7+1):
s = s + x
return s
Well, you could use nested loops..
def sum67(nums):
s=0
flag=1
for n in nums:
while flag:
if n!=6:
s+=n
break
else:
flag=0
while not flag:
if n!=9:
break
else:
flag=1
return s
Just to add, if the last element is a 7 you don’t need to iterate through every element. The question states ” ignore sections of numbers starting with a 6 and extending to the next 7 (every 6 will be followed by at least one 7)”. Once you find a 6 you can simply check if the last element is a 7 and if so simply break out and return the sum; otherwise, you can continue to go through the remaining elements. This is helpful when working with a larger number of elements in an array.
ex. [1, 2, 2, 6, 99, 99, 2, 99, 99, 2, 99, 99, 2, 99, 99, 7]
My solution:
def sum67(arr):
sum = 0
tmp = 0
for n in arr:
if n == 6:
tmp = 6
continue
if tmp == 6:
if n == 7:
tmp = 0
continue
elif arr[-1] == 7:
break
else:
continue
sum += n
return sum
My solution for this I Know this is quite readable but not the best code:
def sum67(nums):
offcount = False
sum = 0
for i in range(len(nums)):
if offcount == False:
if nums[i] == 6:
offcount = True
else:
sum = sum + nums[i]
else:
if nums[i] == 7 :
offcount = False
return sum
I hope this helps:)
def sum67(nums):
result = 0
inside = False
for i in range(len(nums)):
if not inside and nums[i] != 6:
result += nums[i]
if nums[i] == 6:
inside = True
if nums[i] == 7:
inside = False
return result
def sum67(nums):
sum = 0
sumbrake = False
for i in nums:
if i != 6 and sumbrake == False:
sum += i
else:
sumbrake = True
if i == 7:
sumbrake= False
return sum
def sum67(nums):
while nums.count(6) >= 1:
list = (nums[0:nums.index(6)]) + (nums[nums.index(7)+1:len(nums)])
nums = list
return sum(nums)
def sum67(arr):
for n in range (0, len(arr)):
if arr[n] == 6:
Sum1 = sum(arr[0:n])
print ("Before 6 Sum Numbers:", Sum1)
for k in range (0, len(arr)):
if arr[k] ==7:
Sum2 = sum(arr[(k)+1:])
print ("After 7 Sum Numbers:", Sum2)
if 6 and 7 in arr:
print("Last Result")
return (Sum1+Sum2)
else:
print("Last Result")
return sum(arr)
simplified code without while and for loop :
def summer_69(arr):
pos6 = 0;
pos9 = 0;
newArr = [];
if 6 in arr:
pos6 = arr.index(6);
if 9 in arr:
pos9 = arr.index(9);
if 6 in arr and 9 in arr :
newArr = arr[0:pos6] + arr[pos9+1:len(arr)];
else:
newArr = arr;
return sum(newArr);
pass
Maybe a more Pythonian approach?
def sum67(arr):
if (6 in arr):
i1 = arr.index(6)
i2 = arr[i1:].index(7)
res = sum(arr[0:i1]+arr[i1+i2+1:])
else:
res = sum(arr)
return res
Here is my 13 line answer, which uses List index positions to exclude values enclosed by every [6..7] pair.
Technique: Return the sum of array elements upon subtracting the (sum of) excluded elements.
def sum67(nums):
idx_list=[]
for i in range(len(nums)):
if nums[i]==6:
c_6 = i # index pos of 6
j = c_6+1 # counter to find index position of 7
while nums[j]!=7: # stop search when 7 spotted in list
j+=1
c_7 = j # index pos of 7
idx_list += list(range(c_6,c_7+1)) # list of index position(s) of elements to be excluded
idx_main = list(set(idx_list)) # set() removes repeated index positions captured while looping
del_val = [nums[i] for i in idx_main]
return sum(nums)-sum(del_val)
def sum67(nums):
sum=0
sum6=0
for n in nums:
sum+=n
if nums.count(6) >= 1:
a=nums.index(6)
b=nums.index(7)+1
nums67=nums[a:b]
for i in nums67:
sum6 += i
return sum - sum6
This may not the best solution , but its simple and gave correct output all cases
def sum67(nums):
sum = 0
i = 0
while( i < len(nums)):
if nums[i] == 6:
while(nums[i] != 7):
i += 1
else:
sum += nums[i]
i += 1
return sum
Just a short and efficient (O(n) time, O(1) space) alternative, using an iterator:
def sum67(nums):
it = iter(nums)
return sum(x for x in it if x != 6 or 7 not in it)
This mainly sums the values. But whenever a 6 is encountered, the 7 not in it
consumes all values until the next 7 (and it’s false, so none of the values from that 6 to that 7 make it into the sum).
def sum67(nums):
c=0
state=True
for i in nums:
if state:
if i==6:
state=False
else:
c+=i
else:
if i==7:
state=True
return c
def sum_69(arr):
x=arr.index(6)
y=arr.index(9)
if 6 not in arr:
return sum(arr)
else:
sum1=arr[:x]
sum2=arr[y+1:]
sum3=sum1+sum2
return sum(sum3)
may be this will help you:
def sum_67(arr):
while 6 in arr:
del arr[arr.index(6):arr.index(7)+1]
return sum(arr)
def sum67(nums):
cnt = 0
ignore = False
for num in nums:
if not ignore and num == 6:
ignore = True
if not ignore:
cnt = cnt + num
if ignore and num == 7:
ignore = False
return cnt
My approach was to build a new list which consisted only of valid segments ie segments that did not start with a 6 and end with a 7 for that corresponding 6. Then I simply computed the sum of the elements of that new list. Worked perfect in the codingbat exercise platform
def sum67(nums):
lst =[] #holds result after discarding invalid segments
while 6 in nums: # Continue until no more 6's found in nums segment
#Find the first 6
idx6 = nums.index(6)
#Build list upto but excluding the first 6
lst += nums[:idx6]
#Find the next 7
idx7 = nums[idx6:].index(7) # this would be relative to nums[idx6:]
#slice
idx = idx6+idx7 # absolute position of 7 w.r.t nums
nums = nums[idx+1:] # slice from the position of the 7 to end
lst += nums # takes care of any leftovers after the last 7
return sum(lst)
Can be condensed to fewer lines of code but I wanted to maintain readability of code. I am wondering if there is a recursive way to solve this. Working on it.
Thanks everyone for your great alternate solutions
Here is the shortest solution I have seen for this question:
def sum67(nums):
while 6 in nums:
del nums[nums.index(6):nums.index(7,nums.index(6))+1]
return sum(nums)
In my solution, I activate and deactivate with a boolean when a 6 starts and a 7 ends. While in the "active == True" state, the code still functions normally except now there’s a "temp_count". If the array reaches a 7, the "temp_count" will be subtracted from "count".
def sum67(nums):
count = 0
temp_count = 0
active = False
for i in range(len(nums)):
count += nums[i]
if nums[i] == 6:
active = True
if nums[i] == 7 and active == True:
active = False
count = count - temp_count - 7
temp_count = 0
if nums[i] == 6 or active == True:
temp_count += nums[i]
return count
The following code works well too.
def sum67(nums):
total1 = 0
total2 = 0
for y in range(0, len(nums)):
if nums[y] == 6:
total1 = nums[0:y]
if nums[y] == 7:
total2 = nums[y + 1:]
total = total1 + total2
return sum(total)
def sum67(nums):
while 6 in nums:
x = nums[nums.index(6):nums.index(7)+1]
for i in x:
nums.remove(i)
return(sum(nums))