I am using the simple program below to see how long an iterative process takes to terminate. However, in line 15, I cannot figure out why I am getting index out range error.
An example of what I am trying to count is the number of steps it takes for the following example iteration: User inputs 4 and then 1234. Then we have: [1,2,3,4] --> [1,1,1,1] --> [0,0,0,0] and then termination. 2 steps is required to get to [0,0,0,0]. I have proven that for the values of n that I am inserting, the system goes to [0,0,0,0] eventually.
import math
index = input("Enter length: ")
n = int(index)
game = input("Enter Coordinates of length n as a number: ")
s = list(game)
Game = []
for k in s:
Game.append(int(k))
l = len(game)
while sum(Game) > 0:
Iteration = []
k = 0
j = 0
while j < l-1:
Iteration.append(math.fabs(Game[j]-Game[j+1])) # line 15
j = j+1
k = k+1
Game = Iteration
print(k)
Game = Iteration is probably why. When j = 1, Game will be a list with only one item because of that. Then, Game[1]-Game[2] will be out of bounds.
Your code is written in a very un-Pythonic style that suggests you're translating directly from C code. (Also, you should basically never use input(); it's insecure because it evaluates arbitrarily user-entered Python code! Use raw_input() instead.)
If you rewrite it in a more Pythonic style, it becomes clear what the problem is:
import math
# you don't do anything with this value, but okay
s = index = int(raw_input("Enter length: "))
# game/Game naming will lead to confusion in longer code
game = raw_input("Enter Coordinates of length n as a list of comma-separated numbers: ")
Game = [int(k) for k in game.split(',')]
l = len(Game)
while sum(Game) > 0:
Game = [math.fabs(Game[j]-Game[j+1]) for j in range(l-1)] # problem here
# no idea what k is for, but it's not used in the loop anywhere
The problem is that in every iteration through your inner while loop, or the line marked # problem here in my version, your Game list gets shorter by one element! So on the second time through the outer while loop, it reads an element past the end of Game.
I have no idea what this code is trying to do, so I can't really suggest a fix, but if you truly intend to shorten the list on every pass, then you of course need to account for its shorter length by putting l=len(Game) inside the while loop.
Related
I am writing a code on python for the platform Coding Games . The code is about Van Eck's sequence and i pass 66% of the "tests".
Everything is working as expected , the problem is that the process runs out of the time allowed.
Yes , the code is slow.
I am not a python writer and I would like to ask you if you could do any optimization on the piece of code and if your method is complex ( Complex,meaning if you will be using something along vectorized data ) and not just swap an if (because that is easily understandable) to give a good explanation for your choice .
Here is my code for the problem
import sys
import math
def LastSeen(array):
startingIndex = 0
lastIndex = len(array) - 1
closestNum = 0
for startingIndex in range(len(array)-1,-1,-1):
if array[lastIndex] == array[startingIndex] and startingIndex != lastIndex :
closestNum = abs(startingIndex - lastIndex)
break
array.append(closestNum)
return closestNum
def calculateEck(elementFirst,numSeq):
number = numSeq
first = elementFirst
result = 0
sequence.append(first)
sequence.append(0)
number -= 2
while number != 0 :
result = LastSeen(sequence)
number -= 1
print(result)
firstElement = int(input())
numSequence = int(input())
sequence = []
calculateEck(firstElement,numSequence)
so here is my code without dictionaries. van_eck contains the sequence in the end. Usually I would use a dict to track the last position of each element to save runtime. Otherwise you would need to iterate over the list to find the last occurence which can take very long.
Instead of a dict, I simply initialized an array of sufficient size and use it like a dict. To determine its size keep in mind that all numbers in the van-eck sequence are either 0 or tell you how far away the last occurrence is. So the first n numbers of the sequence can never be greater than n. Hence, you can just give the array a length equal to the size of the sequence you want to have in the end.
-1 means the element was not there before.
DIGITS = 100
van_eck = [0]
last_pos = [0] + [-1] * DIGITS
for i in range(DIGITS):
current_element = van_eck[i]
if last_pos[current_element] == -1:
van_eck.append(0)
else:
van_eck.append(i - last_pos[current_element])
last_pos[current_element] = i
I need to write a script that generates random numbers between 1-257000 and stops when a certain number occurs telling me how many numbers it generated so far.
i manged to get this far but can't seem to get it to stop or count
x=1
while x < 257000:
import itertools
import random
def random_gen(low, high):
while True:
yield random.randrange(1, 257000)
gen = random_gen(1, 100)
items = list(itertools.islice(gen, 10))
print items
x = x+1
Thank you so much for your help
Huh. A few flaws (or at least unclear spots) in your code.
You run your loop max 257000 times. Even though the probability is low, there is a chance that you don't hit the number you seek in the loop.
Move your import statements out of your loop, no need to have python check loaded modules each round.
You use a generator for choices of a list (randrange) where you can simply use a randint() call.
You define a closed function within your loop which creates a new function at a new memory address each round.
You slice your results into lists of 10 elements each; is this for printing, or do you actually need your random integers grouped into such lists?
A very simple and straightforward implementation of your described problem could be:
import random
num = 0 # Our counter
certain_number = 123456 # The number we seek
while True: # Run until we break
# Increment for each new step
num += 1
# Generate a single number from the given range
random_number = random.randint(1, 257000)
if random_number == certain_number:
# Break if we hit it
break
print('Hit after {} tries.'.format(num))
>>> Hit after 382001 tries.
First, put your import statements and your function definitons outside your while-loop. That's being super redundant.
>>> def random_gen(low,high):
... while True:
... yield random.randrange(low,high)
...
>>> lucky = 7
>>> rg = random_gen()
>>> rg = random_gen(1,1000)
>>> next(itertools.dropwhile(lambda t: t[1] != lucky, enumerate(rg, 1)))
(811, 7)
>>>
Here's another run, just for fun:
>>> rg = random_gen(1,257000)
>>> n,L = next(itertools.dropwhile(lambda t: t[1] != lucky, enumerate(rg, 1)))
>>> n
22602
>>> L
7
>>>
Hello i'm new to Python and i'm having a little trouble. I'm reading Hello Python
and i'm typing a code down it told me to type, but when i run the code, it gives me an error.
Error: caves[next_cave].append(i) List index out of range
This is the code i'm typing out.
Code:
from random import choice
cave_numbers = range(0,20)
caves = []
for i in cave_numbers:
caves.append([])
unvisited_caves = range(0,20)
visited_caves = [0]
unvisited_caves.remove(0)
while unvisited_caves != []:
i = choice(visited_caves)
if len(caves[i]) >= 3:
continue
next_cave = choice(unvisited_caves)
caves[i].append(next_cave)
caves[next_cave].append(i)
visited_caves.append(next_cave)
unvisited_caves.remove(next_cave)
for number in cave_numbers:
print number, ":", caves[number]
print'-----------'
for i in cave_numbers:
while len(caves[i]) < 3:
passage_to = choice(cave_numbers)
cave[i].append(passage_to)
for number in cave_numbers:
print number, ":", caves[number]
print '----------'
Thank you for answering my question
-Cyr
choice(unvisited_caves) in going to return a number from unvisited_caves = range(0,20), so that would be a random number from 0..19.
caves[next_cave].append(i) will error 90% of the time (18/20 times) because all you have done is caves = [] and caves.append([]), so caves has at most one element in the first iteration of your program.
Maybe you have an indentation problem, but overall, using random numbers of a different range to index a list seems like a bad design.
I think your problem is just with indentation. I believe that your intent was to use the for loop to give your list of caves 20 empty arrays before you begin your simulation. As you had it, your loop would add one array and then start the simulation right away. Your caves list is not ready for this, and so it errors.
The following should work better:
from random import choice
cave_numbers = range(0,20)
caves = []
for i in cave_numbers:
caves.append([])
unvisited_caves = range(0,20)
visited_caves = [0]
unvisited_caves.remove(0)
while unvisited_caves != []:
i = choice(visited_caves)
if len(caves[i]) >= 3:
continue
next_cave = choice(unvisited_caves)
caves[i].append(next_cave)
caves[next_cave].append(i)
visited_caves.append(next_cave)
unvisited_caves.remove(next_cave)
for number in cave_numbers:
print number, ":", caves[number]
print'-----------'
for i in cave_numbers:
while len(caves[i]) < 3:
passage_to = choice(cave_numbers)
caves[i].append(passage_to)
for number in cave_numbers:
print number, ":", caves[number]
print '----------'
I only made two edits:
First, I unindented so that the while loop comes after the for loop finishes
You also had a typo where you said cave[i] instead of caves[i]
Also note, there are some opportunities to simplify your code here. At first this may seem merely aesthetic, but it can actually help avoid errors like this. For example:
for i in cave_numbers:
caves.append([])
can become caves = [ [] for each in cave_numbers] which would have left less room for errors.
That error means that at some point, the value in next_cave exceeds the length of the caves list.
You'd get that same error by doing this:
caves = [[0,1,2], [4,5,6]]
caves[2].append([7,8,9])
My code is showing bellow
import math,sys
#create a list with numbers
def create_list():
num_list=[]
for num in range(int(input("insert start point: ")),int(input("Insert end point: "))):
num_list.append(num)
return num_list
#function to find triangular numbers
def get_triangles(numlist):
triangles = []
for i in numlist:
if (check_triangle(i)):
triangles.append(i)
return triangles
#function to check number is triangular or not
def check_triangle(n):
return math.sqrt((8*n)+1).is_integer()
#function main to run the process
def main():
numlist = create_list()
print(get_triangles(numlist))
Even though it seems like the task is completed it was not. I tried it with the range of 0 - 100000000(1*10^8) numbers . it is cause to stuck my laptop any method that can complete this task ?
DO NOT PRINT A LIST THAT LARGE. Instead write it to a file, that way you can open the file afterward. The program can't efficiently write that much information into the console. I find that printing stuff to the console makes a programs a ton less efficient.
Additionally, I read some of the comments on your code and they state it isn't efficient and I would have to concur.
Here is piece of code I wrote up. It takes a bit of interpretation, but I was in a hurry. Just reply if you need help understanding it.
def getTriangles(input1,input2): #input1 is the min value and input2 is the max value
li = [] #the list where all of the numbers will go
i = 0 #an integer that acts how much another layer of the triangle would have
j = 0 #the most current number that it is on
while True: #I whipped up this algorithm in a couple minutes, so there is probably a more efficient way than just looping through all of them, but it is faster than the current one being used
i += 1 #i has to increment to act as the increase of a side
if j > input2: #if the value that could be added is greater than the max number, than just end the function and return the list
return li
if j >= input1: #if the number qualifies the minimum number requirements, then the program will add it to the list, otherwise it will ignore it and continue on with the function
li.append(j)
j += i #this simulates adding in another layer of the triangle to the bottom
This would be a way to use it:
print(getTriangles(1,45))
I trust you can look up how to write content to a file.
It appears that you are just trying to generate all triangle numbers within a range. If this is so, computing them directly is substantially quicker than checking via square root.
Note that you can generate triangular numbers by simply adding consecutive numbers.
T_0 = 0
T_1 = T_0 + 1 = 1
T_2 = T_1 + 2 = 3
T_3 = T_2 + 3 = 6
...
If you want to keep it simple, you can create a function to keep generating these numbers from n = 0, keeping them when they enter the desired range, and continue until it exceeds the upper bound.
def generate_triangular_numbers(a, b):
"""Generates the triangular numbers in [a, b] (inclusive)"""
n, t = 0, 0
triangles = []
while t < a:
n += 1
t += n
while t <= b:
triangles.append(t)
n += 1
t += n
return triangles
I was told to do this as homework. So far I did the following:
a = raw_input("Please enter a number:")
b = a.split()
for c in range(len(b)):
b[c] = int(b[c])
n=[]
big=b[0]
while b != []:
for i in range(len(b)):
if big < b[i]:
big!=b[i]
n=n+[big]
b.remove(big)
print n
Here's an example:
459113
And the output is suppose to be:
954331
The challenge is not to use sorting algorithms, which is hard for me to do since I don't know how to get around it.
The basis of that program is from:
a = raw_input("Please enter a number:")
b = a.split()
for c in range(len(b)):
b[c] = int(b[c])
n=[]
small=b[0] while b != []:
small=b[0]
for i in range(len(b)):
if small > b[i]:
small=b[i]
n=n+[small]
b.remove(small)
print n
You could try something like this:
a = raw_input("Please enter a number:")
b = map(int, a)
n=[]
while b:
smallest = min(b)
n.append(smallest)
b.remove(smallest)
print
print ''.join(map(str, n))
See it working online: ideone
It's the same algorithm as your existing code, but I've fixed a number of errors. Note that this is not an efficient algorithm. It runs in O(n2) time. Using the builtin sorted function you could achieve O(n log(n)) time, and with a counting sort you could even reach O(n) time.
Note that this sorts in ascending order, not descending order. Since this is homework I'll leave it as an exercise for you to figure out what one thing you need to change to fix this.
Here are some other notes about the changes I made to your program:
Don't call split on your input. That splits on whitespace, which is probably not what you want since your example input doesn't contain any whitespace.
I used map instead of a for loop to convert all elements in a sequence.
I used min to find the smallest value instead of iterating over the sequence.
Maybe not the best way to sort a list but here is another example :)
Im even able to do it without sorting them.
from Queue import Queue
import threading
import time
def sleeper(x, queue):
time.sleep(x)
queue.put(x)
a = [3,2,1,4,3,2,5]
longest = max(a)
threads = {}
queue = Queue()
for num in a:
threads[num] = threading.Thread(target=sleeper, args=(num, queue))
threads[num].start()
threads.get(longest).join()
while not queue.empty():
print queue.get()
For Python you can try the following code :
def Descending_Order(num):
return int("".join(sorted(str(num), reverse=True)))