Multiple python append functions in while loop crashing - python

Attempting to print a composite list by appending item from three smaller lists in sequence:
def final_xyz_lister():
global final_xyz_list
final_xyz_list = []
step=0
while step==0:
final_xyz_list.append(carbon_final_list[step])
final_xyz_list.append(oxygen_final_list[step])
final_xyz_list.append(hydrogen_final_list[step])
step=+1
while 0 < step < 50:
final_xyz_list.append(carbon_final_list[step])
final_xyz_list.append(oxygen_final_list[step])
final_xyz_list.append(hydrogen_final_list[step])
step=+1
else:
pass
If I comment out the second while loop the first element of the list is printed in a list as expected but introduction of the second while loop results in a MemoryError.

There is no need to append the three items in 2 different while loops. It would also be simpler if you used for loops. in this case:
for step in range(0, 50):
final_xyz_list.append(carbon_final_list[step])
final_xyz_list.append(oxygen_final_list[step])
final_xyz_list.append(hydrogen_final_list[step])
Edit: Also, I just noticed the error, you use step =+ 1, which is the same as saying step = +1 or step = 1. This is why you are getting a memory error, you keep defining step as 1, which is between 0 and 50, so the while loop just keeps going. what you probbly wanted to write was step += 1, this increases step by 1 and doesn't set it to 1

Related

Python list first n entries in a custom base number system

I am sorry if the title is a misnomer and/or doesn't properly describe what this is all about, you are welcome to edit the title to make it clear once you understand what this is about.
The thing is very simple, but I find it hard to describe, this thing is sorta like a number system, except it is about lists of integers.
So we start with a list of integers with only zero, foreach iteration we add one to it, until a certain limit is reached, then we insert 1 at the start of the list, and set the second element to 0, then iterate over the second element until the limit is reached again, then we add 1 to the first element and set the second element 0, and when the first element reaches the limit, insert another element with value of 1 to the start of the list, and zero the two elements after it, et cetera.
And just like this, when a place reaches limit, zero the place and the places after it, increase the place before it by one, and when all available places reach limit, add 1 to the left, for example:
0
1
2
1, 0
1, 1
1, 2
2, 0
2, 1
2, 2
1, 0, 0
The limit doesn't have to be three.
This is what I currently have that does something similar to this:
array = []
for c in range(26):
for b in range(26):
for a in range(26):
array.append((c, b, a))
I don't want leading zeroes but I can remove them, but I can't figure out how to do this with a variable number of elements.
What I want is a function that takes two arguments, limit (or base) and number of tuples to be returned, and returns the first n such tuples in order.
This must be very simple, but I just can't figure it out, and Google returns completely irrelevant results, so I am asking for help here.
How can this be done? Any help will truly be appreciated!
Hmm, I was thinking about something like this, but very unfortunately I can't make it work, please help me figure out why it doesn't work and how to make it work:
array = []
numbers = [0]
for i in range(1000):
numbers[-1] += 1
while 26 in numbers:
index = numbers.index(26)
numbers[index:] = [0] * (len(numbers) - index)
if index != 0:
numbers[index - 1] += 1
else:
numbers.insert(0, 1)
array.append(numbers)
I don't quite understand it, my testing shows everything inside the loop work perfectly fine outside the loop, the results are correct, but it just simply magically will not work in a loop, I don't know the reason for this, it is very strange.
I discovered the fact that if I change the last line to print(numbers) then everything prints correctly, but if I use append only the last element will be added, how so?
from math import log
def number_to_base(n,base):
number=[]
for digit in range(int(log(n+0.500001,base)),-1,-1):
number.append(n//base**digit%base)
return number
def first_numbers_in_base(n,base):
numbers=[]
for i in range(n):
numbers.append(tuple(number_to_base(i,base)))
return numbers
#tests:
print(first_numbers_in_base(10,3))
print(number_to_base(1048,10))
print(number_to_base(int("10201122110212",3),3))
print(first_numbers_in_base(25,10))
I finally did it!
The logic is very simple, but the hard part is to figure out why it won't work in a loop, turns out I need to use .copy(), because for whatever reason, doing an in-place modification to a list directly modifies the data reside in its memory space, such behavior modifies the same memory space, and .append() method always appends the latest data in a memory space.
So here is the code:
def steps(base, num):
array = []
numbers = [0]
for i in range(num):
copy = numbers.copy()
copy[-1] += 1
while base in copy:
index = copy.index(base)
copy[index:] = [0] * (len(copy) - index)
if index != 0:
copy[index - 1] += 1
else:
copy.insert(0, 1)
array.append(copy)
numbers = copy
return array
Use it like this:
steps(26, 1000)
For the first 1000 lists in base 26.
Here is a a function, that will satisfy original requirements (returns list of tuples, first tuple represents 0) and is faster than other functions that have been posted to this thread:
def first_numbers_in_base(n,base):
if n<2:
if n:
return [(0,)]
return []
numbers=[(0,),(1,)]
base-=1
l=-1
num=[1]
for i in range(n-2):
if num[-1]==base:
num[-1]=0
for i in range(l,-1,-1):
if num[i]==base:
num[i]=0
else:
num[i]+=1
break
else:
num=[1]+num
l+=1
else:
num[-1]+=1
numbers.append(tuple(num))#replace tuple(num) with num.copy() if you want resutl to contain lists instead of tuples.
return numbers

Python bubble sort breaks with large numbers only

Im trying to create a bubble sort test algorithm that generates x amount of random integers and outputs to console and a text file. The number of numbers created as well as the max value for the random integers is determined by the variable bigsize. The code seems to work up to around when big size is ~2300, sometimes its more and sometimes it's less. I can always get 2000 to work though.
Edit: Also worth noting, it seems that the code breaks during the sorting process, as I get get a file to output unsorted numbers with no issues.
import random
import sys
bigsize = 2000
def main():
sys.setrecursionlimit(7000)
array = create_list()
print_array(array)
bubble_sort(array)
display_out(array)
def create_list():
array = [0] * bigsize
for x in range(bigsize):
array[x] = random.randint(0, bigsize)
return array
def bubble_sort(array):
increment = 0
buffer = 0
for x in range(len(array) - 1):
if (array[increment + 1] <= array[increment]):
buffer = array[increment + 1]
array[increment + 1] = array[increment]
array[increment] = buffer
increment = increment + 1
increment = 0
for x in range(len(array) - 1):
if (array[increment + 1] >= array[increment]):
increment = increment + 1
elif (array[increment + 1] < array[increment]):
bubble_sort(array)
def display_out(array):
for x in range(bigsize):
print(array[x])
main()
You have a dysfunctional sort. First and foremost, there is nothing useful about your recursion: you don't reduce the task -- you simply use recursion in place of the sort's outer loop. At that, you have implemented it incorrectly. I strongly recommend that you get more practice with the more basic skills of programming before you tackle recursion.
The first (non-)problem is a simple inefficiency: your loop has x as the index, but the loop body ignores x, while it maintains increment with the same value. There is no reason to have two separate variables. You can see how this is used in almost any bubble sort on the web:
for pos in range(len(array) - 1):
if array[pos+1] < array[pos]:
# switch the elements
You have a similar inefficiency in the second loop:
increment = 0
for x in range(len(array) - 1):
if (array[increment + 1] >= array[increment]):
increment = increment + 1
Again, you ignore x and maintain increment at the same value ... up until you find elements out of order:
elif (array[increment + 1] < array[increment]):
bubble_sort(array)
When you do so, you recur, but without altering increment. When you return from this recursion, the array must be properly sorted (assuming that the recursion logic is correct), and then you continue with this loop, iterating through the now-sorted array, ensuring up to bigsize times that the array is in order.
This entire loop is silly: if you simply set a flag when you make a switch in the first loop, you'll know whether or not you need to sort again. You'll do one extra iteration, but that doesn't affect the time complexity.
For instance:
done = True
for pos in range(len(array) - 1):
if array[pos+1] < array[pos]:
array[pos], array[pos+1] = array[pos+1], array[pos]
# Replace the second loop entirely
if not done:
bubble_sort(array)
I strongly recommend that you check the operation of your program by properly tracing the results. First, however, clean up the logic. Remove (for now) the superfluous code that writes to files, put in some basic tracing print statements, and study existing bubble sorts to see where you're making this all too "wordy". In fact, remove the recursion and simply repeat the sorting until done.
When I try this with bigsize=5000, it recurs to 3818 levels and quits. I'll leave the tracing up to you, if the problem is still there once you've cleaned up the program. There's not much point to fixing the "silent death" until you tighten the logic and trace the operation, so that you know you're fixing an otherwise working program. The current code does not "Make it easy for others to help you", as the posting guidelines say.

Using a For loop in Python to add up all un-even increments between 3-27?

I am trying to use range() to write a for loop that starts at three and adds up all non-even increments of 3 less than 30. It's supposed to print 75. Here is my code:
for i in range(3,30,3):
sumw=0
if (i%2) != 0:
sumw += i
print(sumw)
^^This is what I have, but it only returns the numbers that are supposed to be added.
Also if you could show me how to do the same thing using a while loop, that would be amazing.
The solution is relatively simple once you realise that the indentation of the final line is such that it prints the running sum after every loop, and that the accumulator is reset inside the loop. What you need to do is stop resetting and then print it once the loop is finished:
sumw = 0
for i in range(3,30,3):
if i % 2 != 0:
sumw += i
print(sumw)
As to using a while loop, the following two are equivalent but I would still maintain that the first is better:
for i in range(3,30,3):
doSomethingWith(i)
i = 3
while i < 30:
doSomethingWith(i)
i += 3
A reasonable general rule is to use the former when you know everything about the loop itself beforehand, that latter when things within the loop may affect how the loop terminates.
And, of course, a more pythonic way to get the sum would be by understanding that odd numbers starting at three can be achieved by adding six rather than three, and using the stuff already built in to Python (the sum function in this case):
sumw = sum(range(3, 30, 6)) # 3, 9, 15, 21, 27.
Using the more expressive parts of Python are a good way to avoid problems such as the one in your original code.
You are close. Your problem is you keep resetting sumw to 0 within the for loop. Try this:
sumw = 0
for i in range(3, 30, 3):
if (i%2) != 0:
sumw += i
print(sumw)
This should print
75
Using a while loop is also trivial:
i = 3
sum = 0
while i < 30:
if (i%2) != 0:
sumw += i
i += 3
As a side note, you can omit the != 0 check and simply write
if i % 2:
Because any non-zero numeric value is logically equivalent to True.
Finally, for future reference, you could have solved the problem in a single line using a generator expression:
>>> print(sum(i for i in range(3, 30, 3) if i % 2))
75

loop through array or list in variable steps

I'm trying to figure out how to loop through an array or list in variable steps.
So for example, if I have the following list...
a = [0,0,1,0,0,1,0]
...and want to use the following logic:
Start at index 0
If index two spots away is a 0, move two spots
If index two spots away is a 1, move one spot
However, I'm not quite clear how I can implement this logic as it seems like I can't change my index value I iterate through.
Why does this snippet still return values from 0-6 instead of 0,3,6?
for idx,val in enumerate(a):
print(idx)
idx+=3
Don't use a for loop.
for loops in python are different than in C or Java. In those languages, a for loop has an initial condition, a termination condition, and an increment for each time the loop runs. Whereas in python, a for loop is more of a for each loop - you give it an iterable object, and it runs the code for every item in that iterable object.
Modifying the iterable object while you're running through it is a bad idea that can have difficult-to-predict repercussions and will usually break your code.
However, you can always use a while loop:
a = [0,0,1,0,0,1,0]
idx = 0
while(idx < len(a) - 2):
print(idx)
if a[idx + 2] == 0:
idx += 2
elif a[idx + 2] == 1:
idx += 1
print(idx)
which produces the expected output
0 1 3 4 6
Or, if you change the increments to 3 and 2 respectively, rather than 2 and 1,
0 2 5
Your reasoning is pretty confusing, and I don't see ANY application for this, but here is how I understand your problem...
The reason is because you aren't actually returning the values, you're simply returning the index + 3, which is wrong to begin with. What you're trying to do is point to a new index of the array based on its value and return the index if it contains a value greater than 0.
You need to reference the index you want, check its value, then return the index which contains a value.
a = [0, 0, 1, 0, 0, 1, 0]
for i, v in enumerate(a):
if i == 0:
print(i)
next
if v == 0:
next
else
print(i)
But let's be honest, this is extremely ugly and un-pythonic. Let's simply check for whether a[i] contains a value, and if so, return the index...
for i, v in enumerate(a):
if v or i == 0:
print(i)
The purpose of if v or i == 0 is to check if v has a value, if so, print the index. OR if we are looking at the first element of i.
If you want to EXPLICITLY move the index by two, you must set your index at the start and use a while loop, since enumerate can't help you here and doesn't actually let you move the indicies...
a = [0, 0, 1, 0, 0, 1, 0]
i = 0
while i < len(a) - 1: # -1 to avoid out of bounds error
print(i)
if a[i + 2] == 0:
i += 2
elif a[i + 2] == 1:
i += 1
print(i) # Final print statement for the last index at the end of the while loop
I want to impress upon you the fact that this solution does NOT scale with different or larger lists, which is why it isn't recommended. By simply checking for whether a value does or doesn't exist, you guarantee your accuracy.
You should simply return the index based upon whether or not it contains a value. Even for very large lists, this will be extremely fast, and will always scale, even for values greater than 1.
The only other reason I would see you would want to do this differently is if you're doing string-search algorithms.
I believe that python refreshes the the variables each iteration. So at the end of the first run, idx would be 3 but then at the start of the second run, it gets reset to 1.
If you want to go through a loop by 3s, you can still use a for loop
for i in range(0,len(a),3):
print(i)
If you want a dynamic iteration value, then you need to use a while loop.
i=0
while i<len(a):
print(i)
if(a[i]==0):
i+=2
else:
i+=1

While loop not exiting Python

Given a list of inputs. The last x of the list, are a number that I want to use for a test. So, the beginning n-x elements are the ones I want to test using the elements in x.
For example:
test_case = [0.18677649597722776, 0.21992417009282958, 0.21001370207789635, 0.2576939078119566, -0.26790678064174844, 0.23723906040549575, 0.23796810219833633, 0.12311570730540798, 0.291222989748139, -0.46589179980005796, -0.5679935337540711, -0.541967302717414, 0.2797199715268191, -0.0462338707795437, 0.3352382038488532, -0.6395453091791992, -0.7116194799285872, -0.6827853559995019, 0.4131897184013285, 0.07125041194386302, 0.47179441094288416, -0.5670171363969451, -0.6493889334859158, -0.6214861349381114, 0.6332084272531783, 0.2946607775328391, 0.7252115985158697, -0.48494480580385074, -0.5584250339723696, -0.5329318548632481, 0, 1, 0, 5, 5, 5]
The last 6 numbers I want to use as part of my test on the first 30 numbers. I want to cycle through the 30 numbers such that when test_case[31] < 3, give me test_case[0], else give me -999. This iterates until test_case[36] < 3, give me test_case[5]. Then I want test_case[31] to go back and be used on test_case[6] and loop again.
After I'm at test_case[30], I want it to stop.
Here's what I have:
def test_inputs(x, comp_size):
counts = x[-comp_size:]
inputs = x[:(len(x)-comp_size+1)]
counts_pos = 0
inputs_pos = 0
while inputs_pos < (len(x)-comp_size+1):
if counts_pos == 6:
counts_pos = 0
if counts[counts_pos] < 3:
x.append(inputs[inputs_pos])
print inputs_pos
print counts_pos
inputs_pos += 1
counts_pos += 1
else:
x.append(-999)
print inputs_pos
print counts_pos
inputs_pos += 1
counts_pos += 1
I'm trying to make a generalized function. In this case, should be able to run:
test_inputs(test_case, 6)
However, this doesn't stop at inputs_pos == 31. I put in print statements, and it looks like it just keeps going.
Is there a simpler way using a filter?
Am I understanding correctly that you want:
from itertools import cycle
def test_inputs(x, comp_size):
return [(input if count<3 else -999) for (input,count)
in zip(x[:-comp_size], cycle(x[-comp_size:]))]
You can restore the in-place modification behaviour by using x.extend instead of return. As the slices are performed before the extend call, it will produce the exact same items. Still, I don't think it's generally a good idea to mix data types in one list like this, when it would be as easy to pass (inputs,counts) tuples.
The loop doesn't stop because len(x) is evaluated at each iteration. In your cycle you increment count_pos and append a new element to x.

Categories

Resources