Is there a way to properly continue this while loop? - python-3.x

I have written a function where the input is a list of numbers (items), where the length is a multiple of 3.
I want to this function to continue, until there is only 1 value left in items.
while len(items) > 1:
for x in range(0, len(items), 3):
if items[x] < items[x+1] < items[x+2] or items[x] > items[x+1] >items[x+2] :
result.append(items[x+1])
elif items[x+1] < items[x] < items[x+2] or items[x+1] > items[x] > items[x+2]:
result.append(items[x])
else:
result.append(items[x+2])
items = result
break
return items

Taking a guess at what you needed and how your code should appear...
items = [99, 42, 17, 7, 1, 9, 12, 77, 15]
while len(items) > 1:
result = []
for x in range(0, len(items), 3):
a, b, c = items[x], items[x+1], items[x+2]
if a < b < c or a > b >c :
result.append(b)
elif b < a < c or b > a > c:
result.append(a)
else:
result.append(c)
items = result
print(items)
Introducing the variables a, b, and c helped me better read the code.

The logic is not quite right. Imagine a simple input of [1, 1, 0]. By looking at this, the median should be 1 but the use of > and < instead of <= and >= end up with the code entering the final else block because 1<1 is False and 1>1 is also False. The final else block sets the result equal to the third element, which is 0.
Switch your operators to >= and <= to fix this. The break at the bottom of your for loop immediately breaks after one iteration, so that also needs to be removed.
If you have a list of one element (3**0 = 1), you will end up with an IndexError when you try to get the 2nd and 3rd elements in your loop.
So we need to
Switch operators to test for equality as well
Remove the erroneous break
Handle the base case
def median_split3(items):
if len(items) == 1: # Base Case
return items[0]
while len(items) > 1:
result = []
for x in range(0, len(items), 3):
a, b, c = items[x:x+3]
if a <= b <= c or a >= b >= c:
result.append(b)
elif b <= a <= c or b >= a >= c:
result.append(a)
else:
result.append(c)
items = result
return items[0]
test1 = [99, 42, 17, 7, 1, 9, 12, 77, 15]
print(test1, "-->", median_split3(test1))
test2 = [1, 1, 0]
print(test2, "-->", median_split3(test2))
test3 = [0, 0, 1]
print(test3, "-->", median_split3(test3))
test4 = [9]
print(test4, "-->", median_split3(test4))
Output:
[99, 42, 17, 7, 1, 9, 12, 77, 15] --> 15
[1, 1, 0] --> 1
[0, 0, 1] --> 0
[9] --> 9

Related

Print the sum of the list of numbers. If the list is empty zero is printed also the element 7 and the element next to it won’t contribute to the sum

I tried solving this way but didn't work. This is a question from geeksforgeeks
arr = [1, 3, 4, 4, 7, 7]
def check(arr):
sums = sum(arr)
if arr == []:
sums = 0
else:
for i in range(len(arr)-1):
if arr[i] == 7:
sums = sums-arr[i]-arr[i+1]
else:
sums = sums
return sums
The question is somewhat vague in defining what "next to it" is, I assumed it's the succeeding element.
So I made a solution with a constraint that literal 7 and number subsequent to 7 are ignored in the summation of the sequence
def check(seq):
return sum(n for i, n in enumerate(seq) if n != 7 and seq[i - (i != 0)] != 7)
Checks that I did on the solution to match the requirements :
assert check([]) == 0, "Empty case"
assert check([1, 7, 8, 1]) == 2, "Exclude 7 and the number next to (8 is ignored) it"
assert check([1, 2, 3, 4, 5, 6, 7]) == 21, "Exclude 7"
assert check([7, 10]) == 0, "7 and 10 are ignored"
If you have an link to the original code challenge then posting it here would be helpful.
def realSum(mylist):
l1=0
v=[]
if len(mylist)>0:
for i in range(len(mylist)):
if mylist[i]==7:
if i not in v or v==[]:
if i!=len(mylist)-1:
v.append(i)
v.append(i+1)
else:
v.append(i)
for i in range(len(mylist)):
if i not in v:
l1+=mylist[i]
return l1
else:
return 0

Counting instances of N in an array using Recursion in Python

I would like to count the number of instances of a given number N in an array using recursion. For example, given:
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
and N = 1, the function should return 5.
This problem can be solved using the .counter attribute as shown here. However, I am looking to not use any in-built functions or attributes.
Here's my attempt to solve this using recursion but I get a count of 1 and not 5. What am I doing wrong?
def count_val(array, n, count=0):
if len(array) == 0:
return None
# Base Case
if len(array) == 1:
if array[0] == n:
count += 1
else:
count_val(array[1:], n, count)
if array[0] == n:
count += 1
return count
print(count_val2(array, 1))
1
I think for an empty array, the value should be 0 (len == 0 should be the base case), and, you don't need to have a count parameter if you just return the count, your function could be reduced to this:
def count_val(array, n):
if len(array) == 0:
return 0
return (array[0] == n) + count_val(array[1:], n)
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
print(count_val(array, 1))
Output:
5
You can have it as a one-liner as well (as suggested by #blhsing):
def count_val(array, n):
return len(array) and (array[0] == n) + count_val(array[1:], n)
What am I doing wrong?
The function you wrote will always keep only the last few characters, so after a while it will be [1, 8, 1], after that [8, 1] and after that [1], which returns 1. The array never contains just any of the other 1s.
An easy way to do this is to loop over all elements in a list and test if they are equal to N.
array = [1, 2, 3, 1, 1, 4, 5, 2, 1, 8, 1]
def count_val(array, n):
if len(array) == 0:
return 0
count=0
for i in array:
if i==n:
count += 1
return count
print(count_val(array, 1))
This returns 5.

How to iterate through a numbered list and every time value 1 appears start over?

Given a list:
list1 = [1,2,3,4,5,6,1,2,3,4,1,2,3,4,5,6,7]
While iterating though list1, every time the integer 1 is hit, start the loop over but increment it by 1.
Tried the two examples below but it only returns a list of 1's for the length of list1.
digit = []
i = 0
for num in list1:
num = i
if num != 1:
i += 1
digit.append(i)
elif num == 1:
digit.append(num)
digit = []
i = 0
for num in list1:
num = i
if num == 1:
digit.append(num)
continue
elif num != 1:
i += 1
digit.append(i)
digit
Looking to get something like the list below
digit = [1,1,1,1,1,1,2,2,2,2,3,3,3,3,3,3,3]
You're overthinking this. Initialise a variable to zero. Append it to a list at each iteration. Increment if the corresponding list value is 1.
values = []
i = 0
for l in list1:
if l == 1: # The check must come before appending. Can you explain why?
i += 1
values.append(i)
values
# [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3]
If you were to ask me for a pythonic solution to this problem, I'd suggest itertools.accumulate:
from itertools import accumulate
from operator import add
list(accumulate((int(x == 1) for x in list1), add))
# [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3]

Euler Project 111 Code to make shorter and shorter

I am solving Euler Project # 111 problem, and the code I wrote is running for too long. How can I write this shorter, simpler, faster?
The problem is the link
https://projecteuler.net/problem=111
result = 0
a = []
count_number = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
for i in range(1000000000, 9999999999):
if i == 2:
result += i
for j in range(1000000000, i):
if i % j == 0:
break
elif j == i -1:
a = list(str(i))
for k in range(len(count_number)):
if a.count(count_number[k]) == 1:
break
elif a.count(count_number[k] == count_number[k]):
result += i
del a
print(result)

how to fix python fibonacci sequence script?

My assignment is to create a function that produces 3 lists of the numbers in the fibonacci sequence starting at 0. Here is my code so far.
def fibList(n):
a = 0; b = 1; fibList = []
if n <= 0:
return
elif n == 1:
fibList = [a]
elif n == 2:
fibList = [a,b]
else:
for i in range(0,n):
a, b = b, a + b
fibList.append(b)
return fibList
def main():
print (fibList(4))
print (fibList(10))
print (fibList(-4))
what i want my output to look like is [0,1,1,2] for 4, [0,1,1,2,3,5,8,13,21,34,55] for 10, and [] for -4
My issue begins with fibList(4) currently giving an output of [1, 2, 3, 5] and fibList(10) gives an output of [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] and for -4 I get "None" instead of a [].
If I type in fibList(1) I get [0] and for fibList(2) I get [0, 1], but when i test fibList(3) the first 0 and 1 are lost, giving me [1,2,3]
How would I go about making it so any number above 3 starts with [0, 1, 1, 2...]? My main issue is getting the 0 and 1 to be the first two numbers in the sequence and getting fibList(-4) to produce a [].
any help or tips would be greatly appreciated :-)
All that you are missing is to add an empty list in the case of less than or equal to zero, and recurse correctly over your range of Fibonacci numbers greater than 2. Making those small changes like so:
def fibList(n):
if n <= 0:
fibnums = []
elif n == 1:
fibnums = [0]
elif n >= 2:
fibnums = [0, 1]
for i in range(2,n):
fibnums.append(fibnums[i-1]+fibnums[i-2])
return fibnums
Note that this recursive method can get quite slow for large numbers, if that is of concern to you with your program. Best of luck!
With these changes,
print (fibList(4)) => [0, 1, 1, 2]
print (fibList(10)) => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print (fibList(-4)) => []
You did not quite define your function. Should the resulting list have n values [f(0), ..., f(n-1)] or n+1 values [f(0), ..., f(n)]? Your examples are contradictory: the 'expected' output for 4 has 4 values ending with f(3) while that for 10 has 11 values ending with f(10).
I am going to assume that the latter is correct. Here is a revised version of your fast iterative solution. (If my assumption is wrong, stop the range at n instead of n+1.)
def fibs(n):
"Return [fib(0), ..., fib(n)."
ret = [0, 1] # fib(0), fib(1)
a, b = ret
if n <= 1:
return ret[:n+1]
else:
for i in range(2, n+1):
a, b = b, a+b # b = f(i)
ret.append(b)
return ret
print(fibs(-4), fibs(0), fibs(2), fibs(4), fibs(10))
#
[] [0] [0, 1, 1] [0, 1, 1, 2, 3] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Resources