Wrinting a program using loop only - python

I was tasked with creating a program that finds all positive integers within a defined range. Currently I'm in school so I am limited to only using loops and functions to make it work (Also note that I have just started learning to use functions.
I've uploaded the picture of it.
my problem lies when I run it instead of printing only the positive values it also prints out 10 000 blank lines. I want that to not be the case.
I think it has something to do with the second else statement.

def getDivisors(number):
divList = []
for x in range(1,number):
if number % x == 0:
divList.append(x)
return divList
def isPerfectNumber(divList,number):
if sum(divList) == number:
return True
else:
return False
for x in range(2,10001):
divList = getDivisors(x)
if isPerfectNumber(divList,x):
print(x,divList)
Looks like that code works. I also had it print out the divison list so you can check verify the numbers for yourself.
Here is my output:
6 [1, 2, 3]
28 [1, 2, 4, 7, 14]
496 [1, 2, 4, 8, 16, 31, 62, 124, 248]
8128 [1, 2, 4, 8, 16, 32, 64, 127, 254, 508, 1016, 2032, 4064]

Related

Python: Parameters to Run the Same Function Multiple Times

I am studying rotating a list, and made a function to rotate the list left and right, but how can I write a code for how many times to rotate? if that makes a sense. I want to pass it as an argument to the functions.
table = [1, 10 ,20, 0, 59, 86, 32, 11, 9, 40]
def rotate_left():
(table.append(table.pop(0)))
return table
print(rotate_left())
def rotate_right():
(table.insert(0,table.pop()))
return table
print(rotate_right())
You can use for loop inside your functions and pass how many times you want to rotate as a argument.
table = [1, 10 ,20, 0, 59, 86, 32, 11, 9, 40]
def rotate_left(rotate_times):
for _ in range(rotate_times):
table.append(table.pop(0))
return table
>>> print(rotate_left(2))
>>> [20, 0, 59, 86, 32, 11, 9, 40, 1, 10]
def rotate_right(rotate_times):
for _ in range(rotate_times):
table.insert(0,table.pop())
return table
>>> print(rotate_right(2))
>>> [1, 10, 20, 0, 59, 86, 32, 11, 9, 40]
NOTE
In above scenario, be aware of the fact that, when you pass a list to a method and modify it inside that method, the changes are made in original list unless you make a deep copy, because list is a mutable type.
So, when you call rotate_left(2), it rotates the original list twice towards left. Then when you call rotate_right(2), it rotates the original list, which is already rotated by rotate_left(2), so we got the list as in initial order.
As, the functions are already modifying the original list, you can remove return table from the function (unless you want a new deep copy of list). And simply print the list after that like:
def rotate_left(rotate_times):
for _ in range(rotate_times):
table.append(table.pop(0))
>>> rotate_left(2)
>>> print(table)
>>> [20, 0, 59, 86, 32, 11, 9, 40, 1, 10]
You can write a 'for loop' and use 'range' to decide how many times you want to rotate. In this example 'rotate_left()' is called three times:
table = [1, 10 ,20, 0, 59, 86, 32, 11, 9, 40]
def rotate_left():
(table.append(table.pop(0)))
return table
def rotate_right():
(table.insert(0,table.pop()))
return table
for i in range(3):
print(rotate_left())
You can write a 'loop' and use 'range' to decide how many times you want to loop. In this example, there is a program that asks the user in which direction and how many times to turn and calculates.
def rotate_left(count,table):
for i in range (count):
(table.append(table.pop(0)))
return table
def rotate_right(count,table):
for i in range (count):
(table.insert(0,table.pop()))
return table
def main():
table = [1, 10 ,20, 0, 59, 86, 32, 11, 9, 40]
isSelect = True
while(isSelect):
rotate = int(input("1- Rotate Left\n2- Rotate Right\n: "))
count = int(input("\nHow many times to rotate ?\n: "))
if((rotate == 1 or rotate == 2) and count > 0):
isSelect = False
if (rotate == 1):
print(rotate_left(count,table))
elif (rotate == 2):
print(rotate_right(count,table))
else:
print("\nInvalid Parameter. Please choose again.\n")
main()

If/else statement with a triplet that sum to a given value

I'm writing a sum up game where two players will take turns picking a random number in the range (1,9), no repeated number allowed. So I'm struggling at
If at any point exactly three of the player's numbers sum to 15, then that player has won.
If the first player picks [7, 2, 3, 5], he will win because 7+3+5 = 15
So my question is why doesn't the program stop when first_player has inputs == 15
I want to avoid importing any libs.
Instead of generating all permutations at each step, maintain a map of what each permutation sums to, then add two branches to each branch at each move.
Think of each entry as a set of bits, ie with each permutation you either include a given entry or not, eg if the numbers are [7, 3, 2] you might store [1, 0, 1] for the combination of the 7 and the 2.
You can make a hashmap of 101->9 etc and when someone adds a 3 to it you add an entry for 1010->9 and 1011->12. As soon as you see the target you know the game is over.
So the evolution of [7, 3, 2] would be
0->0
1->7
00->0
01->3
10->7
11->10
000->0
001->2
010->3
011->5
100->7
101->9
110->10
111->12
A more efficient way would be to find only those numbers whose sum is equal to the target that is 15.
entry = [7, 5, 1, 3]
def is_sum_15(nums):
res = []
search_numbers(nums, 3, 15, 0, [], res)
return len(res) != 0
def search_numbers(nums, k, n, index, path, res):
if k < 0 or n < 0:
return
if k == 0 and n == 0:
res.append(path)
for i in range(index, len(nums)):
search_numbers(nums, k-1, n-nums[i], i+1, path+[nums[i]], res)
print(is_sum_15(entry)) # True
An inefficient but easy way is to use itertools.permutations:
>>> entry = [7, 2, 3, 5]
>>> import itertools
>>> [sum(triplet) for triplet in itertools.permutations(entry, r=3) if sum(tr]
[12, 14, 12, 15, 14, 15, 12, 14, 12, 10, 14, 10, 12, 15, 12, 10, 15, 10, 14, 15, 14, 10, 15, 10]
>>> any(sum(triplet) == 15 for triplet in itertools.permutations(entry, r=3))
True
It's inefficient, because you would be trying all permutations every time entry gets expanded with a new number.

Getting prime numbers from a list

Given a list lst = [121, 4, 37, 441, 7, 16] , I would like to remove from it all numbers that repeat themselves, resulting in a new string that would be lst = [37,7] (the prime numbers of the original string).
So far I'd only managed to put out this code:
def func(lst,x):
y = []
for i in lst:
for x in range (1, i):
if (i % x) == 0 :
y.append(i)
return y
print(func(lst,3))
Instead of getting lst = [37,7], I'm getting this weird looking list:
[121, 121, 4, 4, 37, 441, 441, 441, 441, 441, 441, 441, 441, 7, 16, 16, 16, 16]
Is there any way I can make this work ?
As this feels like a homework question, I won't give working code, but a strategy. You want to ensure that only the numbers of the original list remain, or filter out the numbers that are not prime.
Slightly more formally, "for each number in the list, determine if it's prime, and if so, include it in a new list".
Your code is 90% there, but your kernel (the primality test) is not correct. The key to testing primality is to ensure that each possible integer divisor does not evenly divide the number in question.
For example, if testing 6, the list of possible "0 remainder" integer divisors is
[1, 2, 3, 4, 5, 6]
The first and last numbers (1 and 6) don't mean anything as far as primality (6/1 is 6, and 6/6 is 1). So, your list of possible divisors to test is now
[2, 3, 4, 5]
From here, I think an insight you're missing in your code is that for a number to be prime, all of its possible divisors must not produce an even number (i.e., remainder of 0).
from math import sqrt
def func(n)
list1=[]
list2=[]
for z in (all(i % x for x in range(2,int(sqrt(i)+1))) for i in n):
list1.append(z)
for i,j in enumerate(list1):
if j == True:
list2.append(n[i])
return list2

Handling lists in Python

Suppose I have a list:
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
I want to write a program that prints out all the elements of the list that are less than 10.
Actually its pretty simple I got this program but, I need to do it in a single line and I've no idea how to do that. Need some help with this.
print [x for x in a if x < 10]
Take a further look at lambda functions, I feel this is what you are looking for.
So in order to print something out of a list that is less than 10 In the same line, first you need to create a list:
numbers = []
loop through every single element of the list
for i in a:
And then you need a If statement to check if the element is less than 10
if i < 10:
Append the number to the list
numbers.append(str(i))
Join the results together:
result = " ".join(numbers)
And lastly printing it out
print(result)
And if you combine everything together, this is what you should get:
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
numbers = []
for i in a:
if i < 10:
numbers.append(str(i))
result = " ".join(numbers)
print(result)
The result should be:
1 1 2 3 5 8

Equalizing the elements in a list

I'm attempting to equalize a list of elements. In short, I have an array of x length with each element y being in range from 0 - 100000. To accomplish what I'm trying to do, all elements in the list must be relatively equal to each other (as far as is possible).
Here's some sample output of my current function:
>>> equal([1, 4, 1])
[2, 2, 2]
>>> equal([2, 4, 5, 9])
[5, 5, 5, 5]
>>> equal([2, 2])
[2, 2]
>>> equal([1, 2, 3, 4, 5, 6, 7, 8, 9])
[5, 5, 5, 5, 5, 5, 5, 5, 5]
>>> equal([2, 4, 6, 8, 10, 20, 30, 40])
[15, 15, 15, 15, 15, 15, 15, 15]
>>> equal([343, 452, 948, 283, 394, 238, 283, 984, 236, 847, 203])
[474, 474, 474, 474, 474, 474, 474, 474, 473, 473, 473]
And the associated code:
def equal(l):
# The number of times we distribute to the new loop
loops = reduce(lambda x, y: x + y, l)
# Initializes a new list as such: [0, 0, 0 .. len(l)]
nl = [0 for x in range(len(l))]
# Counts how far we've iterated into our new list
x = 0
for i in range(loops):
# Add 1 to this element and move on to the next element in the list
nl[x] += 1
x += 1
# Ensure we don't traverse past the end of the list
if x > len(nl) - 1:
x = 0
return nl
The problem right now is that once you get to extremely large lists (100+ elements with large values) it gets really slow. Is there some idiom I'm missing here that would make this more efficient?
All of your examples have output lists with all equal integers [*], which of course is not possible in the general case.
[*] except one, where it seems you want earlier items to be bigger, later ones smaller, independently of what original items where big or small; see later if that is in fact your spec.
Assuming (you never actually bother to say that, you know!-) that "all items integers" is a constraint, I'd start with
minel = sum(l) // len(l)
which is the minimum value to assign to each output element. This leaves a "shortage" of
numex = sum(l) - minel * len(l)
items that must be set to minel + 1 to keep the sum equal (another constraint you never clearly express...:-).
Which ones? Presumably those that were largest in the first place.
(Added: or maybe not, according to your last example, where it seems the items that need to be made larger are just the earliest ones. If that's the case, then obviously:
[minel+1] * numex + [minel] * (len(l) - numex)
will be fine. The rest of the answer assumes you may want some connection of input items to corresponding output ones, a harder problem).
So pick those, e.g as bigs = set(heapq.nlargest(l, numex)), and
[minel + (x in bigs) for x in l]
is going to be a pretty close approximation to the "equalized" list you seek (exploiting the fact that a bool is worth 0 or 1 in arithmetic:-).
The one little glitch is for a list with duplicates -- more than numex items might satisfy the x in bigs test!
In this case you presumably want to randomly pick which numex items get to be incremented by 1 (the others staying at minel). But guessing exactly what you want for such a case in your totally under-specified desires is stretching guesses a point too much, so I'll let it rest here for now -- you can clarify your specs, ideally with examples where this formula doesn't do what you exactly want and what you would want instead, by editing your question appropriately.
Here you go. Simply find the whole number average and remainder and return the appropriate number of average+1 and average elements to give the same sum. The code below leverages the builtin divmod to give the whole quotient and remainder, and the fact that multiplying a list such as [x]*5 returns [x,x,x,x,x]:
def equal(l):
q,r = divmod(sum(l),len(l))
return [q+1]*r + [q]*(len(l)-r)
print(equal([2,1]))
print(equal([1, 4, 1]))
print(equal([2, 4, 5, 9]))
print(equal([2, 2]))
print(equal([1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(equal([2, 4, 6, 8, 10, 20, 30, 40]))
print(equal([343, 452, 948, 283, 394, 238, 283, 984, 236, 847, 203]))
Output:
[2, 1]
[2, 2, 2]
[5, 5, 5, 5]
[2, 2]
[5, 5, 5, 5, 5, 5, 5, 5, 5]
[15, 15, 15, 15, 15, 15, 15, 15]
[474, 474, 474, 474, 474, 474, 474, 474, 473, 473, 473]

Categories

Resources