deconstructing word solution - python

I have a word problem I am trying to solve but am getting stuck on a key part.
Initialize n to be 100. Initialize numbers to be a list of numbers from 2 to n, but not including n.
With results starting as the empty list, repeat the following as long as numbers contains any numbers.
Add the first number in numbers to the end of results.
Remove every number in numbers that is evenly divisible by (has no remainder when divided by) the number that you had just added to results.
How long is result?
When n is 100, the length of results is 25.
So far I have understood to set n = 100, and a range(2, 100), results = []
and that the result will be an append situation as in results.append(numbers[]),
but I am having a mental block figuring the key of Remove every number in numbers that is divisible by the number that was added to results.
I know this will be a floor or modulo solution taking from one list to another and working via a while loop. I can also figure the length will be len(results). Any assistance or guidance will be greatly appreciated.

If your new number is newnumber, then you can select only elements from a list which are not divisible by it:
results = [x for x in results if x%newnumber!=0]
results.append(newnumber)
Here newnumber is added afterwards because it is more reasonable to do it (otherwise, it itself would be removed by the filtering).
If you insist on doing it in that order, then it's a bit uglier:
results.append(newnumber)
results = [results[i] for i in range(0,len(results)-1) if results[i]%newnumber!=0]

Related

How to loop through an xarray and calculating using an index in python

I have a data variable(sst) in an xarray(nino6), first I use enumerate to assign each value of data variable of the array an index, then I want to calculate with the values of data variable using the index. This code calculates with the indizes itself instead of the data variable values, but I just wanted you to show what I tried.
How can I loop through an index but actually calculating with the values?
for i, entry in enumerate(nino6['sst']):
a=((i-1)+i+(i+1))/3
ssta.append(a)
I apologise for my question is very likely to be really simple (I just started programming), but I searched unsuccesfully here and and on youtube.
If you are trying to get the average of every 3 adjacent numbers in sst, you do it like this:
lst = nino6['sst']
ssta = []
for i in range(1,len(lst) - 1):
a = (lst[i-1] + lst[i] + lst[i+1])/3
ssta.append(a)
Notice that in this implementation, the length of ssta will be smaller than the length of sst by 2 because the first and last numbers do not have flanking numbers. You can have other variations, where you just get the average of two numbers for the first and last numbers.

Find the element in virtually infinite list

I'm trying to solve this problem:
A list is initialized to ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"], and then undergoes a series of operations. In each operation, the first element of the list is moved to the end of the list and duplicated. For example, in the first operation, the list becomes ["Leonard", "Penny", "Rajesh", "Howard", "Sheldon", "Sheldon"] (with "Sheldon" being moved and duplicated); in the second operation, it becomes ["Penny", "Rajesh", "Howard", "Sheldon", "Sheldon", "Leonard", "Leonard"] (with "Leonard" being moved and duplicated); etc. Given a positive integer n, find the string that is moved and duplicated in the nth operation. [paraphrased from https://codeforces.com/problemset/problem/82/A]
I've written a working solution, but it's too slow when n is huge:
l = ['Sheldon','Leonard','Penny','Rajesh','Howard']
n = int(input()) # taking input from user to print the name of the person
# standing at that position
for i in range(n):
t = l.pop(0)
l.append(t)
l.append(t)
#debug
# print(l)
print(t)
How can I do this faster?
Here's a solution that runs in O(log(input/len(l))) without doing any actual computation (no list operations):
l = ['Sheldon','Leonard','Penny','Rajesh','Howard']
n = int(input()) # taking input from user to print the name of the person
# standing at that position
i = 0
while n>(len(l)*2**i):
n = n - len(l)* (2**i)
i = i + 1
index = int((n-1)/(2**i ))
print(l[index])
Explanation: every time you push back the entire list, the list length will grow by exactly len(l) x 2^i. But you have to first find out how many times this happens. This is what the while is doing (that's what n = n - len(l)* (2**i) is doing). The while stops when it realized that i times of appending the double list will happen. Finally, after you have figured i out, you have to compute the index. But in the i-th appeneded list, every element is copied 2^i times, so you have to devide the number by 2**i. One minor detail is that for the index you have to subtract by 1 because lists in Python are 0-indexed while your input is 1-indexed.
As #khelwood said, you can deduce how many times you have to double the list.
To understand this, note that if you start with a list of 5 people and do 5 steps of your iteration, you will the same order as before just with everyone twice in it.
I am not 100% sure what you mean with the nth position as it shifts all the time, but if you mean the person in front after n iterations, solve for the largest integer i that fulfills
5*2^i<n
to get the number of times your list doubled. Then just look at the remaining list (each name is mentioned i times) to get the name at position n-5*2^i.
You are not going to be able to avoid calculating the list, but maybe you can make it a bit easier:
Every cycle (When sheldon is first again) the length of the list has doubled, so it looks like this:
After 1 cycle: SSLLPPRRHH
After 2 cycles: SSSSLLLLPPPPRRRRHHHH
...
while the number of cola's they drunk is 5*((2**n)-1) where the n is the number of cycles.
So you can calculate the state of the list at the closest ended cycle.
E.g.
Cola number 50:
5*((2**3)) = 40 means that after 40 cokes sheldon is next in line.
Then you can use the algorithm described in the task and get the last one in the line.
Hope this helps.

Generate Random List of Random Length (sort of)

I'm working on a problem from this website:
https://www.practicepython.org/exercise/2014/03/05/05-list-overlap.html
The exercise I'm working on asks us to generate two random integer lists of different lengths. Here is what I've got:
import random
n1 = random.sample(range(1,30), random.randint(5,20))
n2 = random.sample(range(1,40), random.randint(21,40))
n3 = set(n1) & set(n2)
print(n3)
For some reason this runs sometimes and not others.
Here is a screenshot of it not running.
It clearly has something to do with the size of the ranges because the larger I make them the less often I return an Error. But, I'd like to understand why it throws the error in the first place so I can avoid it all together.
Thanks in advance.
random.sample(population,k) returns unique k elements from population
In your case, your population is [1,2,3,...39]. Your k = random.randint(21,40). So you will be getting an exception whenever the k value chosen is 40.
This is documented for random.sample:
Return a k length list of unique elements chosen from the population
sequence. Used for random sampling without replacement.
Your screenshots show you use:
n2 = random.sample(range(1, 30), random.randint(21, 40))
That means you could try to take up to 40 samples from a pool of 30 numbers which, without replacement, is not possible. The examples you gave in code in the actual question don't represent what you're trying to do in reality.

List's and while loops - Python

I am fairly new to Python and I am stuck on a particular question and I thought i'd ask you guys.
The following contains my code so far, aswell as the questions that lie therein:
list=[100,20,30,40 etc...]
Just a list with different numeric values representing an objects weight in grams.
object=0
while len(list)>0:
list_caluclation=list.pop(0)
print(object number:",(object),"evaluates to")
What i want to do next is evaluate the items in the list. So that if we go with index[0], we have a list value of 100. THen i want to separate this into smaller pieces like, for a 100 gram object, one would split it into five 20 gram units. If the value being split up was 35, then it would be one 20 gram unit, on 10 gram unit and one 5 gram unit.
The five units i want to split into are: 20, 10, 5, 1 and 0.5.
If anyone has a quick tip regarding my issue, it would be much appreciated.
Regards
You should think about solving this for a single number first. So what you essentially want to do is split up a number into a partition of known components. This is also known as the Change-making problem. You can choose a greedy algorithm for this that always takes the largest component size as long as it’s still possible:
units = [20, 10, 5, 1, 0.5]
def change (number):
counts = {}
for unit in units:
count, number = divmod(number, unit)
counts[unit] = count
return counts
So this will return a dictionary that maps from each unit to the count of that unit required to get to the target number.
You just need to call that function for each item in your original list.
One way you could do it with a double for loop. The outer loop would be the numbers you input and the inner loop would be the values you want to evaluate (ie [20,10,5,1,0.5]). For each iteration of the inner loop, find how many times the value goes into the number (using the floor method), and then use the modulo operator to reassign the number to be the remainder. On each loop you can have it print out the info that you want :) Im not sure exactly what kind of output you're looking for, but I hope this helps!
Ex:
import math
myList=[100,20,30,40,35]
values=[20,10,5,1,0.5]
for i in myList:
print(str(i)+" evaluates to: ")
for num in values:
evaluation=math.floor(i/num)
print("\t"+str(num)+"'s: "+str(evaluation))
i%=num

Sometimes my set comes out ordered and sometimes not (Python)

So I know that a set is supposed to be an unordered list. I am trying to do some coding of my own and ended up with a weird happening. My set will sometimes go in order from 1 - 100 (when using a larger number) and when I use a smaller number it will stay unordered. Why is that?
#Steps:
#1) Take a number value for total random numbers in 1-100
#2) Put those numbers into a set (which will remove duplicates)
#3) Print that set and the total number of random numbers
import random
randomnums = 0
Min = int(1)
Max = int(100)
print('How many random numbers would you like?')
numsneeded = int(input('Please enter a number. '))
print("\n" * 25)
s = set()
while (randomnums < numsneeded):
number = random.randint(Min, Max)
s.add(number)
randomnums = randomnums + 1
print s
print len(s)
If anyone has any pointers on cleaning up my code I am 100% willing to learn. Thank you for your time!
When the documentation for set says it is an unordered collection, it only means that you can assume no specific order on the elements of the set. The set can choose what internal representation it uses to hold the data, and when you ask for the elements, they might come back in any order at all. The fact that they are sorted in some cases might mean that the set has chosen to store your elements in a sorted manner.
The set can make tradeoff decisions between performance and space depending on factors such as the number of elements in the set. For example, it could store small sets in a list, but larger sets in a tree. The most natural way to retrieve elements from a tree is in sorted order, so that's what could be happening for you.
See also Can Python's set absence of ordering be considered random order? for further info about this.
Sets are implemented with a hash implementation. The hash of an integer is just the integer. To determine where to put the number in the table the remainder of the integer when divided by the table size is used. The table starts with a size of 8, so the numbers 0 to 7 would be placed in their own slot in order, but 8 would be placed in the 0 slot. If you add the numbers 1 to 4 and 8 into an empty set it will display as:
set([8,1,2,3,4])
What happens when 5 is added is that the table has exceeded 2/3rds full. At that point the table is increased in size to 32. When creating the new table the existing table is repopulated into the new table. Now it displays as:
set([1,2,3,4,5,8])
In your example as long as you've added enough entries to cause the table to have 128 entries, then they will all be placed in the table in their own bins in order. If you've only added enough entries that the table has 32 slots, but you are using numbers up to 100 the items won't necessarily be in order.

Categories

Resources