Trying to create finit sequences of numbers in python2: IndexError (beginner) - python

edit: The initial problem is solved now, look at the bottom of the question; I have another problem.
I have a list, s2 that its first element (s[0]) is a list of numbers with the length of n (defined by user input) and its elements are also defined by the user. What I want to do is to create n-1 more sequences of numbers as other elements of s2. Each of those sequences is made of the subtraction of the sequential elements in the previous sequence. (the right element - the left element) so the second sequence's length is n-1, the third: n-2 ... and the nth sequence's length (s2[n-1]'s) is 1.
for j in range(1, n):
for k in range(0,n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
but I get this error:
Traceback (most recent call last):
File "[path]", line 9, in <module>
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
IndexError: list index out of range
Can you help me debug this?
edit:
n = int(raw_input())
s = raw_input()
s1 = [int(i) for i in s.split(" ")]
s2 = []
s2.append(s1)
for j in range(1, n):
for k in range(0,n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
example input:
4
1 2 3 4
ps: Can you suggest me another method to get the nth one faster than this? instead of creating all of these lists? (I want it to take less than 1 sec even when n is very big)

You are referring to s2[j], but haven't created it. Try something like this
for j in range(1, n):
s2.append([])
for k in range(0, n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])

You need to initialize every s2 element before trying to use it. Otherwise how would python know what type it is?
for j in range(1, n):
s2.append(list())
for k in range(0, n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])

Related

Print a number not in a list python

I'm having an issue with a simple task it seems, but cannot figure it out. I believe the solution is within the code:
n = input().split(',')
list1 = []
list2 = []
for x in n:
list1.append(int(x))
for y in range(1, len(list1 + 1)):
if y not in list1:
list2.append(y)
print(list2)
The task is:
Given an array of integers, some elements appear twice and others appear once.
Each integer is in the range of [1, N], where N is the number of elements in the array.
Find all the integers of [1, N] inclusive that do NOT appear in this array.
Constrain:
N will always be in the range of [5, 1000]
Input:
1,2,3,3,5
Output:
4
Input:
1,1,1,1,1,1,1,1
Output:
2,3,4,5,6,7,8
My idea is to have two empty arrays. The first one I will write all the numbers using a for loop. Once I have them all there I will use another loop where I can look and find the missing numbers. I guess it related to some formatting that is killing my logic.
Any help would be appreciated!
Thanks
You only have to change this line:
for y in range(1, len(list1 + 1)):
to this one:
for y in range(1, len(list1)+1):
The problem is that you added one to the list, but you want to add 1 to the length of the list.

determine if list is periodic python

I am curious to find out a function to check if a given list is periodic or not and return the periodic elements. lists are not loaded rather their elements are generated and added on the fly, if this note will make the algorithm easier anyhow.
For example, if the input to the function is [1,2,1,2,1,2,1,2], the output shall be (1,2).
I am looking for some tips and hints on the easier methods to achieve this.
Thanks in advance,
This problem can be solved with the Knuth-Morris-Pratt algorithm for string matching. Please get familiar with the way the fail-links are calculated before you proceed.
Lets consider the list as something like a sequence of values (like a String). Let the size of the list/sequence is n.
Then, you can:
Find the length of the longest proper prefix of your list which is also a suffix. Let the length of the longest proper prefix suffix be len.
If n is divisible by n - len, then the list is periodic and the period is of size len. In this case you can print the first len values.
More info:
GeeksForGeeks article.
Knuth-Morris-Pratt algorithm
NOTE: the original question had python and python-3.x tags, they were edited not by OP, that's why my answer is in python.
I use itertools.cycle and zip to determine if the list is k-periodic for a given k, then just iterate all possible k values (up to half the length of the list).
try this:
from itertools import cycle
def is_k_periodic(lst, k):
if len(lst) < k // 2: # we want the returned part to repaet at least twice... otherwise every list is periodic (1 period of its full self)
return False
return all(x == y for x, y in zip(lst, cycle(lst[:k])))
def is_periodic(lst):
for k in range(1, (len(lst) // 2) + 1):
if is_k_periodic(lst, k):
return tuple(lst[:k])
return None
print(is_periodic([1, 2, 1, 2, 1, 2, 1, 2]))
Output:
(1, 2)
Thank you all for answering my question. Neverthelss, I came up with an implementation that suits my needs.
I will share it here with you looking forward your inputs to optimize it for better performance.
The algorithm is:
assume the input list is periodic.
initialize a pattern list.
go over the list up to its half, for each element i in this first half:
add the element to the pattern list.
check if the pattern is matched throughout the list.
if it matches, declare success and return the pattern list.
else break and start the loop again adding the next element to the pattern list.
If a pattern list is found, check the last k elements of the list where k is len(list) - len(list) modulo the length of the pattern list, if so, return the pattern list, else declare failure.
The code in python:
def check_pattern(nums):
p = []
i = 0
pattern = True
while i < len(nums)//2:
p.append(nums[i])
for j in range(0, len(nums)-(len(nums) % len(p)), len(p)):
if nums[j:j+len(p)] != p:
pattern = False
break
else:
pattern = True
# print(nums[-(len(nums) % len(p)):], p[:(len(nums) % len(p))])
if pattern and nums[-(len(nums) % len(p)) if (len(nums) % len(p)) > 0 else -len(p):] ==\
p[:(len(nums) % len(p)) if (len(nums) % len(p)) > 0 else len(p)]:
return p
i += 1
return 0
This algorithm might be inefficient in terms of performance but it checks the list even if the last elements did not form a complete period.
Any hints or suggestions are highly appreciated.
Thanks in advance,,,
Let L the list. Classic method is: use your favorite algorithm to search the second occurence of the sublist L in the list L+L. If the list is present at index k, then the period is L[:k]:
L L
1 2 1 2 1 2 1 2 | 1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
(This is conceptually identical to #KonstantinYovkov's answer). In Python: example with strings (because Python has no builtin sublist search method):
>>> L = "12121212"
>>> k = (L+L).find(L, 1) # skip the first occurrence
>>> L[:k]
'12'
But:
>>> L = "12121"
>>> k = (L+L).find(L, 1)
>>> L[:k] # k is None => return the whole list
'12121'

Find the Duplicate Number

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
My solution:
def findDuplicate(nums):
slow = fast = finder = 0
while fast is not None:
slow = nums[slow]
fast = nums[nums[fast]]
if fast is slow:
return slow
return False
nums = [1,2,2,3,4]
print findDuplicate(nums)
My above solution works and gives me o/p 2 but it doesn't work for every input for example it doesn't work for [11,15,17,17,14] or [3,1,2,6,2,3] and gives me error IndexError: list index out of range. I am not able to find patterns and am not able to track down the exact problem. Also tried to change my while condition:
while fast is not None and nums[nums[fast]] is not None:
your help will be greatly appreciated! Thank you.
Since the numbers are between 1 and n and you have been told there is only one duplicate, you can use difference between the sum of the numbers in the array and the sum of numbers from 1 to n to get the duplicate.
def findDuplicate(l):
n = len(l) - 1 # Get n as length of list - 1
return sum(l) - (n * (n + 1) / 2) # n*(n+1)/2 is the sum of integers from 1 to n
So the duplicate is the sum of the list - n*(n+1)/2
Of course, this doesn't generalize to finding duplicates for any list. For that case, you need to use #Jalepeno112 's answer.
The fact that the first one works is a fluke. Let's look at what it does on the first pass.
nums = [1,2,2,3,4]
# slow starts as index 0. So now, you've reassigned slow to be nums[0] which is 1.
# so slow equals 1
slow = nums[slow]
# now you are saying that fast equals nums[nums[0]].
# nums[0] is 1. nums[1] is 2
# so fast = 2
fast = nums[nums[fast]]
On the next pass, slow will be nums[1] which is 2. fast will be nums[nums[2]] which is nums[2] which is 2. At this point slow and fast are equal.
In your second example, you are getting an IndexError because of fast = nums[nums[fast]] If the value at nums[fast] is not a valid index, then this code will fail. Specifically in the second example, nums[0] is 11. nums doesn't have an element at index 11, so you get an error.
What you really want to be doing is performing a nested for loop on the array:
# range(0,len(nums)-1) will give a list of numbers from [0, to the length of nums-1)
# range(1, len(nums)) does the same,
# except it will start at 1 more than i is currently at (the next element in the array).
# So it's range is recomputed on each outer loop to be [i+1, length of nums)
for i in range(0,len(nums)-1):
for j in range(i+1,len(nums)):
# if we find a matching element, return it
if nums[i] == nums[j]:
return nums[i]
# if we don't find anything return False
return False
There are likely other more Pythonic ways to achieve this, but that wasn't your original question.
first you must ensure all numbers in list satisfy your constrains.
to find duplicated numbers in a list Use Counter in collections it will return each number and number of occurrence example :
>>> from collections import Counter
>>> l=Counter([11,15,17,17,14])
>>> l
Counter({17: 2, 11: 1, 14: 1, 15: 1})
to get the most common one use :
>>> l.most_common(n=1)
[(17, 2)]
where n is the number most common numbers you want to get
def duplicates(num_list):
if type(num_list) is not list:
print('No list provided')
return
if len(num_list) is 0 or len(num_list) is 1:
print('No duplicates')
return
for index,numA in enumerate(num_list):
num_len = len(num_list)
for indexB in range(index+1, num_len):
if numA == num_list[indexB]:
print('Duplicate Number:'+str(numA))
return
duplicates([11,15,17,17,14])
duplicates([3,1,2,6,2,3])
duplicates([])
duplicates([5])
l=[]
n= int(input("the number of digit is :"))
l=[0 for k in range(n)]
for j in range(0,n):
l[j]=int(input("the component is"))
print(l)
b=0; c=0
for i in range(n):
if l[i]== l[n-1-i]:
b=1;c=i
if b==1:
print("duplicate found! it is",l[c])
elif b==0:
print("no duplicate")
The answer is unfinished. It tries to convert the array to a linked list. So far it found where the slow pointer and fast pointer met, but this is the halfway solution. To get the solution, we need to initialize another pointer from the beginning of the linked list and walk towards each other. When they meet, that point is the where cycle is detected, in our question it is where the single point is:
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
slow,fast=0,0
while True:
slow=nums[slow]
fast=nums[nums[fast]]
if slow==fast:
break
slow2=0
while True:
slow2=nums[slow2]
slow=nums[slow]
if slow==slow2:
return slow2

lndexError: list index out of range

I need to generate a string from random letters given in list take_from. The first time the function was executed it generated a phrase but all my following tries prompted an error "list index out of range". I can`t understand this error in my case and I tried while loop instead of for loop but it did not work either.
from random import randint
def make_a_phrase():
random_string = ''
take_from = ['a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','v','u','w','x',
'y','z',' ']
for i in range(28):
random_string = random_string + take_from[randint
(0,len(take_from))]
return random_string
From the docs
random.randint(a, b)
Return a random integer N such that a <= N <= b.
Alias for randrange(a, b+1).
Therefore you can get values from 0 to len(take_from) - inclusive the endpoints - which in case of the upper bound would be out of list's index range as it is zero based and as such only has len(take_from) - 1 elements
In Python, lists are indexed with integers ranging from 0 to 1 less than the length of the list. E.g., a list with 10 items in it would have indexes from 0 to 9.
Your call to randint() attempts to get indexes from zero to the full length of the list, which will cause this exception. Change it to:
for i in range(28):
random_string = random_string + take_from[randint
(0,len(take_from)-1)]
The reason this happens, is because the len returns the length, but the last index is always the length - 1 (since indices start from 0).
So eventually, the random integer that comes up is the length, and of course, there is no element at that number.
Here is a simple example:
>>> i = [1,2,3]
>>> len(i)
3
>>> i[len(i)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
However, if you -1 from the length you will get the last item:
>>> i[len(i)-1]
3
You should change your loop to say:
for i in range(0, len(take_from)):
You are currently experiencing an off-by-one error because you only have 27 elements in your list, not 28.
You could try something like this instead
from string import ascii_lowercase
import random
def make_a_phrase():
return ''.join(random.choice(ascii_lowercase + ' ') for i in range(28))

Iterate over lists with a particular sum

I would like to iterate over all lists of length n whose elements sum to 2. How can you do this efficiently? Here is a very inefficient method for n = 10. Ultimately I would like to do this for `n > 25'.
n = 10
for L in itertools.product([-1,1], repeat = n):
if (sum(L) == 2):
print L #Do something with L
you only can have a solution of 2 if you have 2 more +1 than -1 so for n==24
a_solution = [-1,]*11 + [1,]*13
now you can just use itertools.permutations to get every permutation of this
for L in itertools.permutations(a_solution): print L
it would probably be faster to use itertools.combinations to eliminate duplicates
for indices in itertools.combinations(range(24),11):
a = numpy.ones(24)
a[list(indices)] = -1
print a
note for you to get 2 the list must be an even length
One way is to stop your product recursion whenever the remaining elements can't make up the target sum.
Specifically, this method would take your itertools.product(...,repeat) apart into a recursive generator, which updates the target sum based on the value of the current list element, and checks to see if the resulting target is achievable before recursing further:
def generate_lists(target, n):
if(n <= 0):
yield []
return
if(target > n or target < -n):
return
for element in [-1,1]:
for list in generate_lists(target-element, n-1):
yield list+[element]

Categories