So I am new to recursion and I am trying to make a program where you can enter a list and python tests each integer (lets say 9 for example) and sees if the integer following it is doubled. So if I entered a list of 2 4 8 16 32, would return 4, and -5 -10 0 6 12 9 36, would return 2 because -5 followed by -10 is one and 6 followed by 12 is the second. This is the code I have so far. I feel like I am very close. but just a few thing stand in my way. Any help would be great!
L = []
def countDouble(L):
x = input(f'Enter a list of numbers separated by a space: ')
y = (x.split(' '))
print(y[1])
print(y[0])
count = 0
y[0] += y[0]
# unsure of how to multiple y[0] by 2
if y[0]*2 == y[1]:
count += 1
else:
count += 0
#how would I traverse through the rest of the entered list using recursion?
print(count)
countDouble(L)
If you want/need to solve it using recursion, the following will do the trick:
def count_sequential_doubles(li, count=0):
return count_sequential_doubles(li[1:], count + int(li[0] * 2 == li[1])) if len(li) > 1 else count
I would suggest this recursive way:
def countDouble(L):
count = 0
if len(L) == 1:
return count
else:
if int(L[0])*2 == int(L[1]):
count += 1
return count + countDouble(L[1:])
x = input(f'Enter a list of numbers separated by a space: ')
y = (x.split(' '))
count = countDouble(y)
print(count)
I urge you to read the entire answer, but in case you are not interested in tips, notes and the process of finding the solution, here are two solutions:
solution using recursion (not recommended):
x = input()
y = x.split(' ')
count = 0
def countDouble(i):
if(i+1 == len(y)):
return 'recursion ends here when'
if(int(y[i])*2==int(y[i+1])):
count += 1
countDouble(i+1)
countDouble(0)
print(count)
this solution just imitates a while loop:
solution using a while loop (recommended):
x = input()
y = x.split(' ')
count = 0
i = 0
while(i < len(y) - 1):
if(int(y[i]) * 2 == int(y[i+1])):
count += 1
i += 1
print(count)
Before I continue, here are a few tips and notes: (some of them will only make sense after)
I assume the 14 in your example is a typo
I didn't put the code in a function because it's not needed, but you can change it easily.
In your code, you are passing L as a parameter to the countDouble() function, but you don't use it. if you don't need a parameter don't pass it.
when splitting the input, the values of the list are still strings. so you have to invert them to integers (for instance, you can do that with the int() 'function') before comparing their values - otherwise multiplying by 2 will just repeat the string. for example: '13'*2 is the string '1313'
I don't know why you why you added y[0] to itself in line 9, but based on the code that comes after this would yield incorrect results, you don't need to change the elements in order to get their value multiplied by 2.
notice that in the else block, nothing has changed. adding 0 to the count doesn't change it. so you can remove the else block entirely
While it's possible to solve the problem in recursion, there's something else designed for these kind of problems: loops.
The problem is essentially repeating a simple check for every element of a list.
This is how I would arrive to a solution
so we want to run the following 'code':
if(y[0]*2 == y[1]):
count += 1
if(y[1]*2 == y[2]):
count += 1
if(y[2]*2 == y[3]):
count += 1
...
of course the computer doesn't understand what "..." means, but it gives us an idea to the pattern in the code. now we can do the following:
divide the extended 'code' into similar sections.
identify the variables in the pattern - the values that change between sections
find the starting values of all variables
find a pattern in the changes of each variable
find a breaking point, a condition on one of the variables that tells us we have reached the last repeating section.
here are the steps in this specific problem:
the sections are the if statements
the variables are the indexes of the elements in y we compare
the first index starts at 0 and the second at 1
both indexes increase by one after each if-statement
when the second index is bigger then the last index of y then we already checked all the elements and we can stop
so all is left is to set the needed variables, have a while loop with the breaking condition we found, and in the while loop have the general case of the repeating sections and then the changing of the variables.
so:
x = input(f'Enter a list of numbers separated by a space: ')
y = (x.split(' '))
count = 0
# setting the starting values of the variables
index1 = 0
index2 = 1
# creating a loop with the breaking condition
while(index2 < len(y)):
# the general case of the repeated code:
if(int(y[index1]) * 2 == int(y[index2])):
count += 1
# changing the variables for the next loop
index1 += 1
index2 += 1
print(count)
We see that the index2 is just index1 + 1 at all time. so we can replace it like that:
x = input(f'Enter a list of numbers separated by a space: ')
y = (x.split(' '))
count = 0
index1 = 0
while(index1 + 1 < len(y)):
if(int(y[index1]) * 2 == int(y[index1 + 1])):
count += 1
index1 += 1
print(count)
Note: You can use a for loop similarly to the while loop
So in summary, you can use recursion to solve the problem, but the recursion would just be imitating the process of a loop:
in each call, the breaking condition will be checked, the repeated code would run and the variables/parameters would change.
Hope you find this answer useful :)
Final edit: OP edited his example so my other code didnt apply
Some good questions people are asking, but in the spirit of helping, here's a recursive function that returns the count of all doubles.
def get_doubles_count_with_recursion(a_list, count, previous=None):
while a_list:
try:
first = previous if previous else a_list.pop(0)
next_item = a_list.pop(0)
except IndexError:
return count
if next_item / 2 == first:
count += 1
return get_doubles_count_with_recursion(a_list, count, next_item)
return count
a_list = [1, 3, 5, 10, 11, 14, 28, 56, 88, 116, 232, 464, 500]
doubles = get_doubles_count_with_recursion(a_list, 0)
print(doubles == 5)
Probably could clean it up a bit, but it's a lot easier to read than the other guy's ;)
If I'm reading your question right, you want a count of all pairs where the 2nd item is double the first. (and the 14 in the first list is a typo). In which case a simple function like this should do the job:
#a = [2,4,8,16,32]
a = [-5, -10, 0, 16, 32]
count = 0
for i, x in enumerate(a):
# Stop before the list overflows
if i < len(a) - 1:
# If the next element is double the current one, increment the counter
if a[i+1] == x * 2:
count = count + 1
else:
break
print(count)
Related
Write a function that takes an array/list of numbers and returns a number.
See the examples and try to guess the pattern:
even_odd([1,2,6,1,6,3,1,9,6]) => 393
even_odd([1,2,3]) => 5
even_odd([0,2,3]) => 3
even_odd([1,0,3]) => 3
even_odd([3,2]) => 6
def even_odd(arr):
count = 0
index = 0
length = len(arr)
while index < length:
for num in range(len(arr)):
if arr[index] % 2 != 0:
count += arr[index]
index += 1
else:
count *= arr[index]
index += 1
return count
So basically the pattern is multiply the first 2 numbers and add the third and I set it to where for each index value if it it was the first number I would add it to the count to keep track and then multiply it with the second number and then add the third. I passed 3/4 sample cases except for one which was the first one ---> even_odd([1,2,6,1,6,3,1,9,6]) => 393. I am just wondering what is the flaw with my logic and does anyone have a better way to solve this that is efficient and clean.
Your question is a challenge on Codewars (https://www.codewars.com/kata/559e708e72d342b0c900007b), so maybe you should use this platform to discuss solutions with other competitiors, instead of Stackoverflow.
The main point of this challange is to investigate the calculated pattern and not the code itself.
If you know the required pattern, the code is easy (Spoiler!):
def even_odd(arr):
num = 0
for i, e in enumerate(arr):
if (i % 2) == 0:
num += e
else:
num *= e
return num
This produces the desired results:
from operator import add, mul
def even_odd(nums):
acc = nums[0] # accumulator
ops = [mul, add]
i = 0
for num in nums[1:]:
acc = ops[i](acc, num)
i = 1 - i # alternates between the two operators
return acc
Write a function div_3_5(start, end) that computes the number of integers from start up to, but not including end that are divisible by 3 or 5 using a while loop.
NOTE: I must use a while loop inside a function for this exercise (i understand that a for loop is best).
Examples:
div_3_5(7, 27) evaluates to 9 ( numbers divisible by 3 or 5 in that range: 9,10,12,15,18,20,21,24,25)
I really don't understand why or what I'm doing and can someone to explain where i went wrong.
This is my code so far:
count = 0
def div_3_5(start, end):
while start < end:
if start%3 == 0 or start%5 == 0:
count + 1
start = start + 1
start + 1
return count
This obviously isn't complete or correct and the current error I'm getting is:
Expected Output:
div_3_5(7, 27) -> 9
Test Result: 0 != 9
There a few tips that would help here.
The mod operation % will return the remainder of an object so it a number is divisible by another the mod will be 0, for example 6 % 3 == 0 returns true.
A while loop isn't the best for this opertation, better would be a for loop
for i in range(start, end+1):
This wil fix the infinite loop.
This is how I would write it:
def div_3_5(start, end):
count = 0
for i in range(start, end + 1):
if i % 3 == 0 or i % 5 == 0:
count += 1
return count
start = 1
end = 10
count = div_3_5(start, end)
print(count)
Python has a modulus operator (%) which returns the remainder of A/B (10%4 == 2).
In your case, you would be looking for numbers which have a remainder of 0 when divided by 3 or 5
(i.e x%3 == 0 OR x%5 == 0).
Finally, the last elif where you ask elif start >= end is unnecessary because you stated that as the condition when you created the loop. Instead, try replacing those 2 lines with start = start + 1
The answer i found was:
def div_3_5(start, end):
count = 0
while start < end:
if start % 3 == int() or start % 5 == int():
count += 1
start = start + 1
return count
You need no loops to accomplish this task, here is simple -and fun- mathematical method that Python allows us to implement easily:
- One, create a set from 0 to the end with steps of 3s, i.e. {0,3,6,...end} this will get you all the elements that are divisible 3 within the boundary of your end (while keeping the end not included), in Python, this is done this way: set_of_3=set(range(0,b,3)) simple eh?
- Two, do the same but for the 5s, set_of_5=set(range(0,b,5))
- Three, add these sets together: set_of_all=set_of_3.union(set_of_5)
Now you got all the elements divisible by 3 and 5 from 0 to end, but you don't want that, you want from beginning to end, simply, just remove all numbers from 0 to your beginning from the set_of_all, by: result = set_of_all - set(range(0,a)) and just return the len() of that result. Your complete code:
def div_3_5(start,end):
set_of_3 = set(range(0,end,3))
set_of_5 = set(range(0,end,5))
set_of_all = set_of_3.union(set_of_5)
result = set_of_all - set(range(0,start))
return len(result)
A bit convoluted I know, but fun! At least for me. Hope this helps.
EDITED
Yeah I didn't notice you said you must use while loop, you can do this version of your code:
def div_3_5(start,end):
list = []
while start<end:
if start%3==0 or start%5==0:
list.append(start)
start+=1
return len(list)
Use the power of Python and forget these C-ish methods, and regarding what is wrong with your code, the line:
count + 1 doesn't work in Python, you have to do this: count+=1
I am creating a basic sudoku checker with the help of Python.
However, the result is always displayed as 'False'.
The code is as follows:
list = [[1,2,3,4],
[2,4,1,3],
[3,1,4,2],
[4,3,2,1]]
def sudoku_check(list):
n = len(list)
digit = 1
while digit <= n:
row_count = 0
col_count = 0
v = 0
while v < n:
x = 0
while x < n:
print ("Check")
if digit == list[v][x]:
row_count = row_count + 1
if digit == list[x][v]:
col_count = col_count + 1
x = x + 1
v = v + 1
if col_count != 1 or row_count != 1:
return False
digit = digit + 1
return True
print (sudoku_check(list))
I am new to programming. Would appreciate your help on this.
Thanks
Alright, have a solution for you/can explain your problem #ShreyashKarnik!
The Problem:
The issue in code comes from the chunk below:
while digit <= n:
row_count = 0
col_count = 0
v = 0
while v < n:
x = 0
while x < n:
print ("Check")
if digit == sudo_board[v][x]:
row_count = row_count + 1
if digit == sudo_board[x][v]:
col_count = col_count + 1
x = x + 1
v = v + 1
if col_count != 1 or row_count != 1:
return False
So what exactly is this code doing? It's going through every cell in your sudoku board and looking for a digit. For the sake of explanation, let's say it's looking for the digit 1. It checks every cell in the entire board, and since 1 appears 4 times total, col_count and row_count will be 4 every time. You can verify this with a print statement if you'd like!
Since your false check is checking against the number 1, it's going to fail every time. So let's start looking for a fix!
Making Things Pythonic
"Pythonic means code that doesn't just get the syntax right but that follows the conventions of the Python community". You say you're new to programming, so learning the proper style of how to write python is important. You have a couple of issues in the code above:
Confusing variable names
Using while loops instead of for loops
Lack of code modularity
Let's start with the last comment, lack of modularity and fix the other things along the way. Determining if a Sudoku grid is valid is actually surprisingly complex -- it has three components.
1. Do all of the rows have the right number of digits?
2. Do all of the columns have the right number of digits?
3. Does the grid as a whole have the right number of digits?
3 is actually a factor of 1 and 2, which you figured out in your code -- nice! But it might make things easier to read if we broke the first and second bit of things into their own functions. How might those look? Let's do rows first. For our function, we'll check each row and confirm that it has the right number of digits.
Let's start with the row checker. All we have to do for that is the following:
def has_correct_number_rows(sudo_board):
# the set we create below is an unordered grouping of the numbers
# 1-4.
correct_set = set(range(1, len(sudo_board)))
for row in sudo_board:
# this if statement checks if our row contains values 1-4
if (correct_set != set(row)):
return False
return True
This will return True if the rows all contain the correct number of items, otherwise it will give false.
Next, the checking the correct number of columns. This is slightly more complicated, but still fairly simple:
def has_correct_number_cols(sudo_board):
correct_set = set(range(1, len(sudo_board) + 1))
for col_num in range(0, len(sudo_board)):
# col_set creates a set of the elements in a given column
col_set = set([row[col_num] for row in sudo_board])
if (correct_set != set(row)):
return False
return True
Same return values here.
Putting it all together
Now that you have these two functions, your final check is actually very easy. It's below:
def sudoku_check_peter(sudo_board):
correct_rows = has_correct_number_rows(sudo_board)
correct_cols = has_correct_number_cols(sudo_board)
# This last line returns True if both are true, otherwise
# False.
return correct_rows and correct_cols
This ended up being quite wordy which I apologize for -- happy to answer follow up questions or explain anything more! hope this helps.
myList = []
size = int(input("How many integers do you want in your list? "))
for list in range(size):
element = int(input("Enter an integer to add to your list: "))
myList.append(element)
print(myList)
#a function that keeps count of all even integers using while loop
def count_evens_while(alist):
evenIntegers = 0
while range <= size:
for element in range(size):
if element % 2 == 0:
evenIntegers = evenIntegers + 1
print(evenIntegers)
This is what I have so far. I can't figure out what I need to do! (I'm a beginner, so sorry if this question seems so simple/easy to fix)
def count_evens_while(alist):
evenIntegers = 0
idx = 0
while idx < len(alist):
if alist[idx] % 2 == 0:
evenIntegers = evenIntegers + 1
idx += 1
print(evenIntegers)
Using a for loop would be much simpler though:
def count_evens_while(alist):
evenIntegers = 0
for el in alist:
if el % 2 == 0:
evenIntegers = evenIntegers + 1
print(evenIntegers)
And even simpler using some list comprehension:
def count_evens_while(alist):
evenIntegers = sum(1 for x in alist if (x%2 == 0))
print(evenIntegers)
Problem
You have several problems here:
You never define size in the head of the while loop.
You're using the range builtin class as an integer value which doesn't make sense.
You never use alist in your function.
You don't need a for loop in your while because you are not trying to find the amount of even numbers for each number between 1 to element, your trying to find all the even numbers in alist (presumably).
Here is what the above fixes would look like:
def count_evens_while(alist):
evenIntegers = 0
size = 0
while size < len(alist):
if alist[size] % 2 == 0:
evenIntegers = evenIntegers + 1
size = size + 1
print(evenIntegers)
In the first part of the while loop:
size < len(alist)
We are telling Python to comparse the value of size to the length of alist each time we loop. We then incrmenet size by one each time in the loop:
size = size + 1
This basically means that each iteration of the loop, the value of size will correspond to an index of alist. The loop will stop when size reaches the last index of alist. Here's a visual example to help explain. Assume alist is [1, 2, 3] and size initially equals 0:
First iteration
alist = [1, 2, 3]
^
|
+--- size = 0
Second iteration
alist = [1, 2, 3]
^
|
+--- size = 1
Third (and last) iteration
alist = [1, 2, 3]
^
|
+--- size = 2
The next important part:
alist[size] % 2 == 0
Means we are indexing the list alist. When you index a list, you use an integer to get a value from the position that the integer corresponds to. In this case, alist[size] means that we are getting the value of the integer at position of the value of size. The last part:
% 2 == 0
Means that we are testing if the integer at position size in alist is even. If it is, we increment the count of even numbers, if not we do nothing.
Improvements
There are some improvements you can make to your current solution
Use a for loop instead of a while loop. It would be the more natural solution here.
You don't need to do evenIntegers = evenIntegers + 1. You an use the increment operator, +=, instead.
Here are the improvements from above applied to your code:
def count_evens_while(alist):
evenIntegers = 0
for element in alist:
if element % 2 == 0:
evenIntegers += 1
print(evenIntegers)
However, this can be improved more! You don't need a for loop. You can use a generator comprehension combined with the sum() builtin function to count all of the elements in alist that are even:
def count_evens_while(alist):
return sum(1 for el in alist if el % 2)
Stylistic improvements
The last thing I would critique on your code would be to use better variable names. Use names that accurately describe what the variable represents.For example, the variable myList would be better renamed to user_input_numbers.
You do not need a while loop at all:
myList = []
size = int(input("How many integers do you want in your list? "))
for list in range(size):
element = int(input("Enter an integer to add to your list: "))
myList.append(element)
print(myList)
#a function that keeps count of all even integers using while loop
def count_evens_while(alist):
evenIntegers = 0
for element in alist:
if element % 2 == 0:
evenIntegers = evenIntegers + 1
return evenIntegers
print(count_evens_while(myList))
If you need to stop a for loop early, you can use the break statement to break out of the loop. Otherwise, it will stop by itself once it reaches the end of the list. It does not need an ending condition to be given manually.
This is very unlike your program but I hope to teach you something with it... First of all if all you need is to "keep count" you don't really have to save the integers themselves in a list. Which means that all you really need is something like this:
count = 0
while True:
element = int(input("Enter an integer to add to your list: "))
if element % 2 == 0:
count += 1 # which is the same as count = count + 1
elif element == 9999:
break # user could enter 9999 to exit the loop
print('I have counted ' + str(count) + ' even numbers so far')
I hope in this just to show you that you don't have to complicate simple things
def is_prime(x):
count = 1
my_list = []
while count > 0 and count < x:
if x % count == 0:
my_list.append(x/count)
count += 1
return my_list
my_list = is_prime(18)
def prime(x):
my_list2 = []
for number in my_list:
if number <= 2:
my_list2.append(number)
else:
count = 2
while count < number:
if number % count == 0:
break
else:
my_list2.append(number)
count += 1
return my_list2
print prime(18)
Just started out with Python. I have a very simple question.
This prints: [9, 3, 2].
Can someone please tell me why the loop inside my else stops at count = 2? In other words, the loop inside my loop doesn't seem to loop. If I can get my loop to work, hopefully this should print [2, 3]. Any insight is appreciated!
Assuming that my_list2 (not a very nice name for a list) is supposed to contain only the primes from my_list, you need to change your logic a little bit. At the moment, 9 is being added to the list because 9 % 2 != 0. Then 9 % 3 is tested and the loop breaks but 9 has already been added to the list.
You need to ensure that each number has no factors before adding it to the list.
There are much neater ways to do this but they involve things that you may potentially find confusing if you're new to python. This way is pretty close to your original attempt. Note that I've changed your variable names! I have also made use of the x that you are passing to get_prime_factors (in your question you were passing it to the function but not using it). Instead of using the global my_list I have called the function get_factors from within get_prime_factors. Alternatively you could pass in a list - I have shown the changes this would require in comments.
def get_factors(x):
count = 1
my_list = []
while count > 0 and count < x:
if x % count == 0:
my_list.append(x/count)
count += 1
return my_list
# Passing in the number # Passing in a list instead
def get_prime_factors(x): # get_prime_factors(factors):
prime_factors = []
for number in get_factors(x): # for number in factors:
if number <= 2:
prime_factors.append(number)
else:
count = 2
prime = True
while count < number:
if number % count == 0:
prime = False
count += 1
if prime:
prime_factors.append(number)
return prime_factors
print get_prime_factors(18)
output:
[3, 2]
Just to give you a taste of some of the more advanced ways you could go about doing this, get_prime_factors could be reduced to something like this:
def get_prime_factors(x):
prime_factors = []
for n in get_factors(x):
if n <= 2 or all(n % count != 0 for count in xrange(2, n)):
prime_factors.append(n)
return prime_factors
all is a built-in function which would be very useful here. It returns true if everything it iterates through is true. xrange (range on python 3) allows you to iterate through a list of values without manually specifying a counter. You could go further than this too:
def get_prime_factors(x):
return [n for n in get_factors(x) if n <= 2 or all(n % c != 0 for c in xrange(2, n))]