The Padovan sequence is governed by the relationship P(n+1) = P(n-1) + P(n-2), for n is a
non-negative integer, where P(0) = P(1) = P(2) = 1. So, for instance, P(3) = 2, P(4) = 2, and
P (5) = 3, and so on.
I want to write a Python program Pad(n) that generates the sequence P(0), P(1), ..., P(n - 1).
This is what I have this far, but it only produces a list with the ith number replicated up to the largest number in the sequence:
def ith(n):
first, sec, third, fourth = 1, 1, 1, 1
for i in range(3, n+1):
fourth = first + sec
first = sec
sec = third
third = fourth
return fourth
def pad(n):
pad = ith(n)
lst = []
for i in range(n):
lst.append(pad)
return lst
I want it to produce this as an output:
>>> Pad(6)
>>>[1,1,1,2,2,3]
Currently my code only produces:
>>>[4,4,4,4,4,4]
I now that I append the ith value ith number of times to the list, but I dont know how to append each number in series up to and including the value for the last number. Pad(6) yields 4 since this is all the previous relationships put together.
Sorry for my bad description and formulating of the problem.
You have a two minor errors in your pad() function.
First you should be calling the ith() function inside the loop (also don't name the variable pad as that's the name of the function and it can cause problems).
Secondly, you are calling ith(n) inside the loop when you should be calling ith(i). This is the reason that you were always getting the same number- the argument to ith() was not changing inside the loop.
A fixed version of your pad() function would be:
def pad(n):
lst = []
for i in range(n):
val = ith(i)
lst.append(val)
return lst
You can verify that this indeed produces the correct output of [1, 1, 1, 2, 2, 3] for pad(6).
More efficient non-recursive method
Now, while your method works, it's also very inefficient. You are calling the ith() function for every value in range(n) which recomputes the entire sequence from the beginning each time.
A better way would be to store the intermediate results in a list, rather than by calling a function to get the ith() value.
Here is an example of a better way:
def pad2(n):
lst = [1, 1, 1] # initialize the list to the first three values in the sequence
for i in range(3,n):
lst.append(lst[i-2] + lst[i-3]) # use already computed values!
# slice the list to only return first n values (to handle case of n <= 3)
return lst[:n]
Recursive method
As seen on Wikipedia, the recurrence relation shows us that pad(n) = pad(n-2) + pad(n-3).
Use this as the starting point for a recursive function: return pad(n-2) + pad(n-3)
This is almost everything you need, except we have to define the starting values for the sequence. So just return 1 if n < 3, otherwise use the recurrence relation:
def pad_recursive(n):
if n < 3:
return 1
else:
return pad_recursive(n-2) + pad_recursive(n-3)
Then you can get the first n values in the sequence via list comprehension:
print([pad_recursive(n) for n in range(6)])
#[1, 1, 1, 2, 2, 3]
But this suffers from the same drawback as your original function as it computes the entire sequence from scratch in each iteration.
Related
First, I want to find the highest number in the list which is the second number in the list, then split it in two parts. The first part contains the 2nd highest number, while the second part contains the number from the list that sums to the highest number. Then, return the list
eg: input: [4,9,6,3,2], expected output:[4,6,3,6,3,2] 6+3 sums to 9 which is the highest number in the list
Please code it without itertools.
python
def length(s):
val=max(s)
s.remove(val)
for j in s:
if j + j == val:
s.append(j)
s.append(j)
return s
Here's what I have but it doesn't return what the description states.
Any help would be appreciated as I spent DAYS on this.
Thanks,
The main issue in your code seems to be that you are editing the list s whilst iterating through it, which can cause issues with the compiler and is generally just something you want to avoid doing in programming. A solution to this could be iterating through a copy of the original list.
The second problem is that your program doesn't actually find the second biggest value in the list, just a value which doubles to give you the biggest value.
The final problem (which I unfortunately only noticed after uploading what I thought was a solution) is that the split values are appended to the end of the list rather than to the position where originally the largest value was.
Hopefully this helps:
def length(array):
val = max(array)
idx = array.index(val) # gets the position of the highest value in the array (val)
array.remove(val)
for i in array.copy(): # creates a copy of the original list which we can iterate through without causing buggy behaviour
if max(array) + i == val:
array = array[:idx] + [max(array), i] + array[idx:]
# Redefines the list by placing inside of it: all values in the list upto the previous highest values, the 2 values we got from splitting the highest value, and all values which previously went after the highest value.
return array
This will return None if there is no value which can be added to the second highest value to get the highest value in the given array.
Input:
print(length([1,2,3,4,5]))
print(length([4,8,4,3,2]))
print(length([11,17,3,2,20]))
print(length([11,17,3,2,21]))
Output:
[1, 2, 3, 4, 4, 1]
[4, 4, 4, 4, 3, 2]
[11, 17, 3, 2, 17, 3]
None
Here are the docs on list slicing (which are impossible to understand) and a handy tutorial.
when you say "The first part contains the 2nd highest number" does that mean second highest number from the list or the larger of the two numbers that add up the largest number from list?
Here I assume you just wanted the larger of the two numbers that add up to the largest number to come first.
def length(s:list):
#start by finding the largest value and it's position in the list:
largest_pos = 0
for i in range(len(s)):
if s[i] > s[largest_pos]:
largest_pos = i
# find two numbers that add up to the largest number in the s
for trail in range(len(s)):
for lead in range(trail, len(s)):
if (s[trail] + s[lead]) == s[largest_pos]:
if s[trail] > s[lead]:
s[largest_pos] = s[trail]
s.insert(largest_pos +1, s[lead])
else:
s[largest_pos] = s[lead]
s.insert(largest_pos + 1, s[trail])
return s
# if no two numbers add up to the largest number. return s
return s
Since you are limited to 2 numbers, a simple nested loop works.
def length(s):
val = max(s)
idx = s.index(val)
s.remove(val)
for i in range(len(s) - 1):
for j in range(i + 1, len(s)):
if s[i] + s[j] == val:
s = s[:idx] + [s[i], s[j]] + s[idx:]
return s
print(length([4,9,6,3,2]))
Output:
[4, 6, 3, 6, 3, 2]
I used deque library
first to find the highest element or elements then remove all of them and replace them with second high value and rest like : 9 replace with 6 and 3 in example:
from collections import deque
l = [4, 9, 6, 3, 2]
a = deque(l)
e = a.copy()
s = max(a)
while s in a:
a.remove(s) # remove all highest elements
s2 = max(a) # find second high value
c = s - s2
for i in l:
if i == s:
w = e.index(i) # find index of high values
e.remove(max(e))
e.insert(w, s2)
e.insert(w+1, c)
print(list(e))
I need to make a "folded in half list" where I multiply the first and last term, second and second to last term, third and third to last term, etc.
I know how to make a list and how to print specific values from the list, but don't understand how to do math like this within the list, without simply typing each number and multiplying them.
So far all I have is a list (called a) with six terms, and though I know how to multiply the whole times an integer, I don't know how to make this "folded" thing. Will I need to end up making a loop of some sort? If so, how?
Edit: I should have specified that I need to make it via a function. Someone helped me make one via a method that worked great, but when I realized it needed to be a function I tried it again and it won't work. See the code below.
a = [10, 14, 21, 25 ,52, 55]
print('starting list:', a)
Finding the middle of the list
len(a)//2
Using (what I think is) a function to make a new list of first + last term, etc.
Term i is the term counted from the start of the list, term -(i+1) is the term counted from the bottom of the list
print(sum((a[i]) + (a[-(i + 1) ])) for i in range( len(a) // 2)
A code that works but isn't a function since it has brackets
foldedlist=[ a[i] + a[-(i + 1) ] for i in range( len(a) // 2)]
print('folded list:', foldedlist)
Take your list, here:
l = [1, 2, 3, 4, 5, 6]
Find the mid-way point (where the fold happens - you'll need to think about how this works for an odd-numbered length list)
l_mid = len(l) / 2
Make two sublists up to, and then from the mid-point
l1 = l[:l_mid]
l2 = l[l_mid:]
Create a container for the output and then iterate over both lists, with the latter reversed and append the product to the container.
output = []
for v1, v2 in zip(l1, reversed(l2)):
output.append(v1 * v2)
As we know, indexes in list can be positive or negative. Index -1 refers to last item, index -2 refers to second last item, etc. Hence, we must have:
L[0]*L[-1]+
L[1]*L[-2]+
L[2]*L[-3]+
...+
L[mid]*L[-(mid+1)]
The general formula is: L[i]*L[-(i+1)]. So, we can use the following code:
list = [1, 2, 3, 4, 5, 6]
newList=[ list[i] * list[-(i + 1) ] for i in range( len(list) // 2)]
print(newList)
len(list) // 2 is the index of middle of list.
Output: [6, 10, 12]
Try like this:
myList = [Yourlist]
newList = []
a = myList[:len(myList)//2]
b = myList[len(myList)//2:]
b.reverse()
for x,y in zip(a,b):
newList.append(x*y)
This is a Find All Numbers Disappeared in an Array problem from LeetCode:
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array),
some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may
assume the returned list does not count as extra space.
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]
My code is below - I think its O(N) but interviewer disagrees
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
results_list=[]
for i in range(1,len(nums)+1):
if i not in nums:
results_list.append(i)
return results_list
You can implement an algorithm where you loop through each element of the list and set each element at index i to a negative integer if the list contains the element i as one of the values,. You can then add each index i which is positive to your list of missing items. It doesn't take any additional space and uses at the most 3 for loops(not nested), which makes the complexity O(3*n), which is basically O(n). This site explains it much better and also provides the source code.
edit- I have added the code in case someone wants it:
#The input list and the output list
input = [4, 5, 3, 3, 1, 7, 10, 4, 5, 3]
missing_elements = []
#Loop through each element i and set input[i - 1] to -input[i - 1]. abs() is necessary for
#this or it shows an error
for i in input:
if(input[abs(i) - 1] > 0):
input[abs(i) - 1] = -input[abs(i) - 1]
#Loop through the list again and append each positive value to output list
for i in range(0, len(input)):
if input[i] > 0:
missing_elements.append(i + 1)
For me using loops is not the best way to do it because loops increase the complexity of the given problem. You can try doing it with sets.
def findMissingNums(input_arr):
max_num = max(input_arr) # get max number from input list/array
input_set = set(input_arr) # convert input array into a set
set_num = set(range(1,max(input_arr)+1)) #create a set of all num from 1 to n (n is the max from the input array)
missing_nums = list(set_num - input_set) # take difference of both sets and convert to list/array
return missing_nums
input_arr = [4,3,2,7,8,2,3,1] # 1 <= input_arr[i] <= n
print(findMissingNums(input_arr)) # outputs [5 , 6]```
Use hash table, or dictionary in Python:
def findDisappearedNumbers(self, nums):
hash_table={}
for i in range(1,len(nums)+1):
hash_table[i] = False
for num in nums:
hash_table[num] = True
for i in range(1,len(nums)+1):
if not hash_table[i]:
print("missing..",i)
Try the following :
a=input() #[4,3,2,7,8,2,3,1]
b=[x for x in range(1,len(a)+1)]
c,d=set(a),set(b)
print(list(d-c))
I'm trying to get this function to return the index of the smallest value in a list. It works for every case besides if the smallest value is the last element of the list. Can anyone spot my mistake?
def rotation_point(rotated_list):
length = len(rotated_list)
for i in range (0,length-1):
if rotated_list[i]<rotated_list[(i+1)%length] and rotated_list[i]<rotated_list[i-1]:
return i
else:
pass
I know it has something to do with the first part of the if statement, but I can't see why it wouldnt work.
The if statement itself works just fine but you never actually check the last element because you use: range(0,length-1) for the range of the for loop. The range function already stops at length - 1. You should use: range(0,length).
Note that you also don't really need the 0 since range already starts at zero by default, and there is no need for the else: pass since the use of an else statement is not required, removing it would change nothing.
This is what a working (and cleaner) version of your function would look like:
def rotation_point(rotated_list):
length = len(rotated_list)
for i in range (length):
if rotated_list[i]<rotated_list[(i+1)%length] and rotated_list[i]<rotated_list[i-1]:
return i
Here are some more examples of the range function:
>>> range(0, 5-1)
[0, 1, 2, 3]
>>> range(0, 5)
[0, 1, 2, 3, 4]
>>> range(5)
[0, 1, 2, 3, 4]
Note that range(i, j) goes from i to j - 1. Since you are using range(0, length - 1), you are not traversing the entire array, just from the start to the second last index. A super easy fix is to add return length - 1 to the end.
def rotation_point(rotated_list):
length = len(rotated_list)
for i in range (0,length-1):
if rotated_list[i]<rotated_list[(i+1)%length] and rotated_list[i]<rotated_list[i-1]:
return i
else:
pass
return length - 1
I am creating a makeChange function using a useIt or loseIt recursive call. I was able to determine the least amount of coins that's needed to create the amount; however, I am unsure as to how to display the actual coins used.
def change(amount,coins):
'''takes the amount and makes it out of the given coins in the list in order to return the least number of coins that's needed to create the value and the coins used'''
if amount==0:
return 0
if coins== [] or amount < 0:
return float('inf')
else:
useIt= change(amount,coins[1:])
loseIt= change(amount-coins[0],coins) + 1
return min(useIt,loseIt)
First of all the semantics of your names for the use-it-or-lose-it strategy are backwards. "Use it" means the element in question is being factored into your total result. "Lose it" means you're simply recursing on the rest of the list without considering the current element. So I'd start by switching those names around. And also you should be discarding the current element in the recursive call, whether or not you use it:
loseIt = change(amount,coins[1:])
useIt = change(amount-coins[0], coins[1:]) + 1
Now that we've fixed that, on to your question about passing the result down. You can take the min of tuples or lists, and it will start by comparing the first elements of each, and continue on successive elements if no definite min is yet found. For example if you pass around a list with an integer and a list:
>>> min([2, [1,2]], [3, [0,2]])
[2, [1, 2]]
You can also combine any number of elements in this form with an expression like this:
>>> [x+y for x,y in zip([2, [1,2]], [3, [0,2]])]
[5, [1, 2, 0, 2]]
but your case is easier since you always are just combining 2 of these, so it can be written more like:
[useIt[0] + 1, useIt[1] + [coins[0]]]
Note that the first element is an integer and the second a list.
in your case the implementation of this idea would look something like:
def change(amount,coins):
if amount==0:
return [0, []]
if coins== [] or amount < 0:
return [float('inf'), []]
else:
loseIt = change(amount, coins[1:])
useIt = change(amount - coins[0], coins[1:])
# Here we add the current stuff indicating that we "use" it
useIt = [useIt[0] + 1, useIt[1] + [coins[0]]]
return min(useIt,loseIt)
You want something like:
def change(amount, coins):
'''
>>> change(10, [1, 5, 25])
[5, 5]
'''
if not coins or amount <= 0:
return []
else:
return min((change(amount - coin, coins) + [coin]
for coin in coins if amount >= coin), key=len)
As an aside, this is not a dynamic programming solution. This is a simple recursive algorithm which will not scale for very large inputs.