Can't seem to get this for loop to work with range - python-3.x

numbers = [5, 9, 13, 17, 21]
for list in range(5,22,4):
print(numbers[list], end =" ")
Can't seem to get it to work, keep getting
IndexError: list index out of range

Your numbers variable has an index from 0-4 (python starts at 0 and increments from there) - your range command is giving you the numbers:
[5, 9, 13, 17, 21]
You're telling python that you want to go from the number 5 to the number 22, in steps of 4. This means that when you try and print numbers[list], the variable list is actually the index 5 on the iteration of the for loop, and will be outside of the index range of the numbers variable, since it only has indices 0, 1, 2, 3, and 4

Your code seems to confuse two approaches to solving the same task.
One is printing the existing list of numbers:
numbers = [5, 9, 13, 17, 21]
for number in numbers:
print(number, end=" ")
# or, alternatively
for index in range(len(numbers)):
print(numbers[index], end=" ")
Another is generating the same sequence of numbers using range() function:
for number in range(5,22,4):
print(number, end=" ")
# or, reusing one of the previous approaches
numbers = range(5,22,4)
for number in numbers:
print(number, end=" ")
Bear in mind that range() creates a range object, which is suitable for enumeration and indexing, but does not support other list operations like slicing, concatenation and repeating (concatenation with itself). If you want to get numbers as a list, write explicitly:
numbers = list(range(5,22,4))
and then you can do:
for number in numbers * 2:
print(number, end=" ")
which will print your sequence of numbers twice.

Related

Can't get a descending sorted list. Its sorting for positive number but not for negative numbers. Why? Please see output below. Python version 3.9.7

This question is for my assignment so I can't use built-in function for max and sorting
myMax() returns the maximum number from a list and mySort() sorts in descending order
Input I am giving
Please enter a list of different numbers separated by ',' : 1,-3,4.5,5,18,-1,3,-4
def myMax(a_list):
max_num=a_list[0]
print(a_list)
location=0
counter=1
list_size=len(a_list)
while(counter<list_size):
if(max_num<a_list[counter]):
max_num=a_list[counter]
location=counter+1
counter+=1
return max_num,location
def mySort(a_list):
list_size=len(a_list)
counter=0
des_list=[]
while(counter<list_size):
max_num,location=myMax(a_list)
des_list.append(max_num)
a_list.pop(location-1)
counter+=1
return des_list
input_list= input("Please enter a list of different numbers separated by ',' : ")
input_list=input_list.split(",")
input_list=[int(i) for i in input_list]
print("The descending sorted list is {}.".format(mySort(input_list)))
Input:
1,-3,4.5,5,18,-1,3,-4
Output I am getting:
The descending sorted list is [18, 5, 4.5, 3, 1, 1, 1, 1]
Output I am expecting:
The descending sorted list is [18, 5, 4.5, 3, 1,-1,-3,-4]

Improving While-Loop with Numpy

I have given the following three variables:
start = 30 #starting value
end = 60 #ending value
slice_size = 6 #value difference per tuble
start and end are row numbers of an array. My goal is to create an array/list of tuples, where each tuples includes as much items as slice_size defines. A little example: If start and end have the above values the first four tuples would be:
[[30,35],[36,41],[42,47],[48,53],...].
But now comes the clue: the first value of the next tuple does not start with the first value before + slice_size, but rather with first value + slice_size/2. So I want something like this:
[[30,35],[33,38],[36,41],[39,44],...].
This list of tuples goes on until end is reached or right before it is reached - so until <=end . The last value of the list is not allowed to pass the value of end. The value of slice_size must of course always be an even number to work properly.
My nooby attempt is done by a while loop:
condition = 0
i = 0
list = []
half_slice = int(slice_size /2)
while condition <= end:
list.append([start+int(slice_size/2)*i,start+((slice_size-1)+i*half_slice)])
condition = start+((slice_size-1)+i*int(slice_size/2))
i += 1
The thing is, it works. However I know this is complete rubbish and I want to improve my skill. Do you have a suggestion how to do it in a couple of code lines?
you must not use list as it is a reserved word
import numpy as np
start = 30 #starting value
end = 60 #ending value
slice_size = 6 #value difference per tuble
l = [[i,j] for i,j in zip(np.arange(start, end, slice_size/2),
np.arange(start + slice_size - 1,
end + slice_size - 1,
slice_size/2)
)
]
print(l)
Output:
[[30.0, 35.0],
[33.0, 38.0],
[36.0, 41.0],
[39.0, 44.0],
[42.0, 47.0],
[45.0, 50.0],
[48.0, 53.0],
[51.0, 56.0],
[54.0, 59.0],
[57.0, 62.0]]
1) Do NOT use list as a variable name. It is a reserved key-word.
2) Not a NumPy solution but you can use list comprehension:
start = 30 #starting value
end = 60 #ending value
slice_size = 6 #value difference per tuble
result = [[current, current + slice_size - 1] for current in range(start, end - slice_size + 2, slice_size // 2)]
print(result)
Output:
[[30, 35], [33, 38], [36, 41], [39, 44], [42, 47], [45, 50], [48, 53], [51, 56], [54, 59]]
This will work for an odd number slice_size as well.

python random lottery number generator game

I have to make a game where like the lottery my program generates 5 random numbers from a list of numbers 1-50 and one additional number from a list of numbers 1-20 and combines them into a final list that reads eg: (20, 26, 49, 01, 11, + 06) where two numbers are never repeated like (22, 11, 34, 44, 01, + 22) <--- this is what I don't want
attached below is the code I have written yet how do I make it so two numbers or more are never repeated and to add the + into my list without the "" signs
input:
import random
a = list(range(1,51))
b = random.randint(1, 20)
temp = []
for i in range(5):
random.shuffle(a)
temp.append(random.choice(a[:5]))
temp.append('+')
temp.append(b)
print(temp)
output:
[14, 12, 3, 16, 23, '+', 9]
You can not add + without the ' around them - they mark the + as string.
Also: you shuffle your list - simply take the first 5 values - they are random and your list does not contain any dupes so you are golden:
nums = list(range(1,51))
random.shuffle(nums)
five_nums = nums[:5]
print(five_nums) # [44, 23, 34, 38, 3]
To simplyfy it, use:
import random
# creates 5 unique elements from 1..50 and adds a + and a [0-19]+1 number
randlist = random.sample(range(1,51),k=5) + ["+", random.choice(range(20))+1]
print(randlist)
Now you got mixed numbers and strings - you can create a combined string by:
print("You drew {} {} {} {} {} {} {}".format(*randlist))
To create a string like
[48, 2, 9, 6, 41, '+', 8]
You drew 48 2 9 6 41 + 8
Doku:
random.sample (draw without putting back)
You can try the following:
import random
randList, run = [], 0
while run < 6:
number = random.randint(1,51)
if number not in randList:
if run == 5:
randList.append('+'+str(number))
break
randList.append(number)
run += 1
print(randList)
You can't have a string in a list without quotes, however, if you were to print every item in the list (using a for loop or join), the quotes wouldn't be there.
This code will generate a list of 7 random numbers
import random
def main():
numbers = []
for num in range(7):
num = random.randrange(50)
numbers.append(num)
print(numbers)
main()
#No repeating numbers and sorted output
import random
picks = int (input("How Many Picks ?: "))
for i in range (picks):
num_list = random.sample(range(1, 45), 5,)
num_list.sort()
joker_num = random.sample(range(1, 20), 1)
print("Lucky Numbers :", num_list, "-", "Joker :", joker_num)
It didn't work because you need to have
import random

python 3 function with one argument returning list of integers

how the 're' function should look like if it must receive just one argument 's' and must return a list with the numbers (integers) from 1 to 12 incl. (for example)?
so the result in the interactive console have to be:
>>> re(12)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
First of all you used def incorrectly, if you want to define you have to enter : and define function in additional indentation below, or if you want to use function, you have to remove def.
Python has built-in range() immutable sequence type, which takes one to three arguments start, stop and step, in this case we only will use first two. However to get list we also need to use another built-in, which is mutable sequence type - list(), you can read more about lists in here. We will use list() as the type constructor: list() or list(iterable) as specified in built-in types page:
Lists may be constructed in several ways:
Using a pair of square brackets to denote the empty list: []
Using square brackets, separating items with commas: [a], [a, b, c]
Using a list comprehension: [x for x in iterable]
Using the type constructor: list() or list(iterable)
The constructor builds a list whose items are the same and in the same
order as iterable’s items. iterable may be either a sequence, a
container that supports iteration, or an iterator object. If iterable
is already a list, a copy is made and returned, similar to
iterable[:]. For example, list('abc') returns ['a', 'b', 'c'] and
list( (1, 2, 3) ) returns [1, 2, 3]. If no argument is given, the
constructor creates a new empty list, [].
Now that we understand how list() works, we can go back to range() usage:
The arguments to the range constructor must be integers (either built-in int or any object that implements the index special
method). If the step argument is omitted, it defaults to 1. If the
start argument is omitted, it defaults to 0. If step is zero,
ValueError is raised.
For a positive step, the contents of a range r are determined by the formula r[i] = start + step*i where i >= 0 and r[i] < stop.
For a negative step, the contents of the range are still determined by the formula r[i] = start + step*i, but the constraints
are i >= 0 and r[i] > stop.
A range object will be empty if r[0] does not meet the value constraint. Ranges do support negative indices, but these are
interpreted as indexing from the end of the sequence determined by the
positive indices.
Ranges containing absolute values larger than sys.maxsize are permitted but some features (such as len()) may raise OverflowError.
Range examples:
>>>
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(range(0, 30, 5))
[0, 5, 10, 15, 20, 25]
>>> list(range(0, 10, 3))
[0, 3, 6, 9]
>>> list(range(0, -10, -1))
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
>>> list(range(0))
[]
>>> list(range(1, 0))
[]
Ranges implement all of the common sequence operations except concatenation and repetition (due to the fact that range objects can
only represent sequences that follow a strict pattern and repetition
and concatenation will usually violate that pattern).
start:
The value of the start parameter (or 0 if the parameter was not supplied)
stop:
The value of the stop parameter
step:
The value of the step parameter (or 1 if the parameter was not supplied)
Many other operations also produce lists, including the sorted() built-in.
The answer to your question looks like that:
def re(ending_number):
return list(range(1, ending_number + 1))
list_of_twelve = re(12) # list_of_twelve will contain [1, 2, ..., 12]
I would avoid using "re" as a function name, since re is also a python library for regex expressions.
Lycopersicum's answer does a good job of explaining range(), which is the fastest and most straight-forward way of approaching your problem. In general, it is best to use Python's built-in functions, that's because it will use Python's compiled C code rather than slower Python code.
I just thought I'd share a little bit about why you should use Range().
So, there are other ways to generate a list of numbers. First generate a list directly using a loop.
def listOfNumbers (number):
start = 1
listOf = []
while (start <= number):
listOf.append(start)
start = start + 1
return listOf
In this case, you simply use listOfNumbers(12) and you will get a list of numbers. However, this stores a list in memory and is slow, so not good for very large numbers.
On the other hand, you could use a generator (which is very much like range()). A generator does not store data in a list. Instead, it just "yields" numbers one at a time until the code stops. It's much faster:
def generatorOfNumbers (number):
start = 1
while start <= number:
yield start
start += 1
Then you can call it one of two ways to produce a list:
def listFromGenerator1 (number):
return [x for x in generatorOfNumbers(number)]
def listFromGenerator2 (number):
return list(generatorOfNumbers (number))
When I time these approaches I get.
timed(listOfNumbers) # time for list of 10000
...
Elapsed Time: 2.16007232666
Elapsed Time: 1.32894515991
Elapsed Time: 2.09093093872
Elapsed Time: 1.99699401855
Elapsed Time: 3.2000541687
... timed(listFromGenerator1)
...
Elapsed Time: 1.33109092712
Elapsed Time: 1.30605697632
Elapsed Time: 1.93309783936
Elapsed Time: 1.79386138916
Elapsed Time: 1.90401077271
... timed(listFromGenerator2)
...
Elapsed Time: 0.869989395142
Elapsed Time: 1.08408927917
Elapsed Time: 1.65319442749
Elapsed Time: 1.53398513794
Elapsed Time: 1.36089324951
... timed(listFromRange) # Lycopersicum's approach
...
Elapsed Time: 0.346899032593
Elapsed Time: 0.284194946289
Elapsed Time: 0.282049179077
Elapsed Time: 0.295877456665
Elapsed Time: 0.303983688354
In conclusion, always use built-in functions whenever possible rather than trying to build your own. That includes the (slight) preference for list() vs a list comprehension.

Get a list of all number in a certain range containing only certain digits without checking each number

Is there a way to create a list of all numbers less than 10,000 that do not contain any of the digits 0, 2, 4, 5, 6, 8? Of course one can simply type something like:
bads = ['0', '2', '4', '5', '6', '8']
goods = []
for n in range(1, 10000, 2):
if not any(bad in str(n) for bad in bads):
goods.append(n)
However, I'm looking for a method which instead considers the digits 1, 3, 7, 9 and creates all possible unique strings of permutations of these numbers of size 4 or less, duplicate digits allowed. Does itertools, for example, have something that would easily do this? I looked at the permutations method, but that doesn't produce numbers with repeated digits from the collection, and the product method doesn't seem to be what I'm after either, given that it simply would return Cartesian products of 1, 3, 5, 7 with itself.
Here's a simple-minded approach using permutations and combinations_with_replacement from itertools:
from itertools import permutations, combinations_with_replacement
def digit_combinations(power_of_ten):
numbers = set()
for n in range(1, power_of_ten + 1):
for combination in combinations_with_replacement("1379", n):
numbers |= set(permutations(combination, len(combination)))
return sorted(int(''.join(number)) for number in numbers)
print(digit_combinations(4))
OUTPUT
[1, 3, 7, 9, 11, 13, 17, 19, ..., 9971, 9973, 9977, 9979, 9991, 9993, 9997, 9999]
It could be made more space efficient using generators, but depending on the range, it might not be worth it. (For up to 10,000 there are only 340 numbers.) For numbers to 10^4, this code takes roughly as long as your simple example. But for 10^7, this code runs over 40x faster on my system than your simple example.
Could you include your idea for the generator?
Here's a basic rework of the code above into generator form:
from itertools import permutations, combinations_with_replacement
def digit_combinations_generator(power_of_ten):
for n in range(1, power_of_ten + 1):
for combination in combinations_with_replacement("1379", n):
for number in set(permutations(combination, len(combination))):
yield int(''.join(number))
generator = digit_combinations_generator(4)
while True:
try:
print(next(generator), end=', ')
except StopIteration:
print()
break
This does not return the numbers sorted, it just hands them out as fast as it generates them.

Resources