def voting_borda(rank_ballots):
'''(list of list of str) -> tuple of (str, list of int)
The parameter is a list of 4-element lists that represent rank ballots for a single riding.
The Borda Count is determined by assigning points according to ranking. A party gets 3 points for each first-choice ranking, 2 points for each second-choice ranking and 1 point for each third-choice ranking. (No points are awarded for being ranked fourth.) For example, the rank ballot shown above would contribute 3 points to the Liberal count, 2 points to the Green count and 1 point to the CPC count. The party that receives the most points wins the seat.
Return a tuple where the first element is the name of the winning party according to Borda Count and the second element is a four-element list that contains the total number of points for each party. The order of the list elements corresponds to the order of the parties in PARTY_INDICES.
#>>> voting_borda([['GREEN','NDP', 'LIBERAL', 'CPC'], ['GREEN','CPC','LIBERAL','NDP'],
['LIBERAL','NDP', 'CPC', 'GREEN']])
#('GREEN',[4, 6, 5, 3])
list_of_party_order = []
for sublist in rank_ballots:
for party in sublist[0]:
if party == 'GREEN':
GREEN_COUNT += 3
elif party == 'NDP':
NDP_COUNT += 3
elif party == 'LIBERAL':
LIBERAL_COUNT += 3
elif party == 'CPC':
CPC_COUNT += 3
for party in sublist[1]:
if party == 'GREEN':
GREEN_COUNT += 2
elif party == 'NDP':
NDP_COUNT += 2
elif party == 'LIBERAL':
LIBERAL_COUNT += 2
elif party == 'CPC':
CPC_COUNT += 2
for party in sublist[2]:
if party == 'GREEN':
GREEN_COUNT += 1
elif party == 'NDP':
NDP_COUNT += 1
elif party == 'LIBERAL':
LIBERAL_COUNT += 1
elif party == 'CPC':
CPC_COUNT += 1
I don't know how I would give points for each indices of the list MORE SIMPLY.
Can someone please help me? Without being too complicated. Thank you!
This does not do EXACTLY what you were asking for, it returns a tuple with two values: winner's name, and a dictionary of all parties and their values, instead of a list with only values. In my opinion, this is better for almost any case, and if you don't like it, you can convert it to a list.
It also takes multiple parameters instead of one list too, but you can change that by simply removing the * from *args
Notice, however, if you care about speed rather than small code, this is not the best way to do it. It does work, tho.
It is also superior to your code in the manner of this allowing you to NOT use any of the parties names or amount of parties inside the function, which makes it possible to add, rename or remove parties.
def voting_borda(*args):
results = {}
for sublist in args:
for i in range(0, 3):
if sublist[i] in results:
results[sublist[i]] += 3-i
else:
results[sublist[i]] = 3-i
winner = max(results, key=results.get)
return winner, results
print(voting_borda(
['GREEN','NDP', 'LIBERAL', 'CPC'],
['GREEN','CPC','LIBERAL','NDP'],
['LIBERAL','NDP', 'CPC', 'GREEN']
))
Will result into: ('GREEN', {'LIBERAL': 5, 'NDP': 4, 'GREEN': 6, 'CPC': 3})
I found your voting simulation assignment online and added a few of the constants from it here to simplify the code for solving the problem a little (although it may not look like it with their definitions at the beginning).
The first element of the tuple returned is not exactly in the requested format -- it's a list rather than a single value -- to deal with the quite real possibility of tie votes, as illustrated with the sample data values used below for rank_ballots. Even if there wasn't a tie, the element is return is a singleton list -- which actually is usually easier to deal with than having it vary depending on there's more than one or not.
PARTY_NAMES = ['NDP', 'GREEN', 'LIBERAL', 'CPC']
NAME_TO_INDEX = {party:PARTY_NAMES.index(party) for party in PARTY_NAMES}
INDEX_TO_NAME = {PARTY_NAMES.index(party):party for party in PARTY_NAMES}
def voting_borda(rank_ballots):
results = [0 for _ in PARTY_NAMES]
MAX_POINTS = len(PARTY_NAMES)-1
for ballot in rank_ballots:
for i,party in enumerate(ballot):
results[NAME_TO_INDEX[party]] += MAX_POINTS-i
highest_rank = max(results)
winners = [INDEX_TO_NAME[i] for i,total in enumerate(results) if total == highest_rank]
return winners, results
rank_ballots = [['GREEN','NDP', 'LIBERAL', 'CPC'],
['GREEN','CPC','LIBERAL','NDP'],
['LIBERAL', 'GREEN', 'NDP', 'CPC'],
['LIBERAL','NDP', 'CPC', 'GREEN'],]
print(voting_borda(rank_ballots))
Output:
(['GREEN', 'LIBERAL'], [5, 8, 8, 3])
Related
For the given sorted list,the program should return the index of the number in the list which is greater than the number which is given as input.
Now when i run code and check if it is working i am getting 2 outputs. One is the value and other output is None.
If say i gave a input of 3 for the below code.The expected output is index of 20 i.e., 1 instead i am getting 1 followed by None.
If i give any value that is greater than the one present in the list i am getting correct output i.e., "The entered number is greater than the numbers in the list"
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a,num_to_find):
j = i = 0
while j==0:
if a[len(a)-1] > num_to_find:
if num_to_find < a[i]:
j=1
print(i)
break
else:
i = i + 1
else:
ret_state = "The entered number is greater than the numbers in the list"
return ret_state
print(occur1(a,num_to_find))
This code is difficult to reason about due to extra variables, poor variable names (j is typically used as an index, not a bool flag), usage of break, nested conditionals and side effect. It's also inefficient because it needs to visit each element in the list in the worst case scenario and fails to take advantage of the sorted nature of the list to the fullest. However, it appears working.
Your first misunderstanding is likely that print(i) is printing the index of the next largest element rather than the element itself. In your example call of occur1([2, 20, 30], 3)), 1 is where 20 lives in the array.
Secondly, once the found element is printed, the function returns None after it breaks from the loop, and print dutifully prints None. Hopefully this explains your output--you can use return a[i] in place of break to fix your immediate problem and meet your expectations.
Having said that, Python has a builtin module for this: bisect. Here's an example:
from bisect import bisect_right
a = [1, 2, 5, 6, 8, 9, 15]
index_of_next_largest = bisect_right(a, 6)
print(a[index_of_next_largest]) # => 8
If the next number greater than k is out of bounds, you can try/except that or use a conditional to report the failure as you see fit. This function takes advantage of the fact that the list is sorted using a binary search algorithm, which cuts the search space in half on every step. The time complexity is O(log(n)), which is very fast.
If you do wish to stick with a linear algorithm similar to your solution, you can simplify your logic to:
def occur1(a, num_to_find):
for n in a:
if n > num_to_find:
return n
# test it...
a = [2, 5, 10]
for i in range(11):
print(i, " -> ", occur1(a, i))
Output:
0 -> 2
1 -> 2
2 -> 5
3 -> 5
4 -> 5
5 -> 10
6 -> 10
7 -> 10
8 -> 10
9 -> 10
10 -> None
Or, if you want the index of the next largest number:
def occur1(a, num_to_find):
for i, n in enumerate(a):
if n > num_to_find:
return i
But I want to stress that the binary search is, by every measure, far superior to the linear search. For a list of a billion elements, the binary search will make about 20 comparisons in the worst case where the linear version will make a billion comparisons. The only reason not to use it is if the list can't be guaranteed to be pre-sorted, which isn't the case here.
To make this more concrete, you can play with this program (but use the builtin module in practice):
import random
def bisect_right(a, target, lo=0, hi=None, cmps=0):
if hi is None:
hi = len(a)
mid = (hi - lo) // 2 + lo
cmps += 1
if lo <= hi and mid < len(a):
if a[mid] < target:
return bisect_right(a, target, mid + 1, hi, cmps)
elif a[mid] > target:
return bisect_right(a, target, lo, mid - 1, cmps)
else:
return cmps, mid + 1
return cmps, mid + 1
def linear_search(a, target, cmps=0):
for i, n in enumerate(a):
cmps += 1
if n > target:
return cmps, i
return cmps, i
if __name__ == "__main__":
random.seed(42)
trials = 10**3
list_size = 10**4
binary_search_cmps = 0
linear_search_cmps = 0
for n in range(trials):
test_list = sorted([random.randint(0, list_size) for _ in range(list_size)])
test_target = random.randint(0, list_size)
res = bisect_right(test_list, test_target)[0]
binary_search_cmps += res
linear_search_cmps += linear_search(test_list, test_target)[0]
binary_search_avg = binary_search_cmps / trials
linear_search_avg = linear_search_cmps / trials
s = "%s search made %d comparisons across \n%d searches on random lists of %d elements\n(found the element in an average of %d comparisons\nper search)\n"
print(s % ("binary", binary_search_cmps, trials, list_size, binary_search_avg))
print(s % ("linear", linear_search_cmps, trials, list_size, linear_search_avg))
Output:
binary search made 12820 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 12 comparisons
per search)
linear search made 5013525 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 5013 comparisons
per search)
The more elements you add, the worse the situation looks for the linear search.
I would do something along the lines of:
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a, num_to_find):
for i in a:
if not i <= num_to_find:
return a.index(i)
return "The entered number is greater than the numbers in the list"
print(occur1(a, num_to_find))
Which gives the output of 1 (when inputting 3).
The reason yours gives you 2 outputs, is because you have 2 print statements inside your code.
We have unlimited coins of different values - Calculate the unique combinations of how these coins can make up a specific amount. For example:
n = 4 (say, 4 cents)
coins_list = [1,2] - we have 1-cent coins, and 2-cent coins
The different combinations would be 112, 1111, and 22. (121 and 211 should be excluded since it's not unique - using one 2-cent coin and two 1-cent coin)
I have watched this video: https://www.youtube.com/watch?v=k4y5Pr0YVhg
countless number of times, and edited my codes countless number of times, but I cannot manage to get rid of the same combination of different orders.
def make_change(n, coinlist_index=None):
coin_list = [1, 2]
if coinlist_index == None:
coinlist_index = 0
#coin index position in coin_list; starts at index 0 and cycles through all the coins
if n == 0:
return 1
if n < 0:
return 0
ways = 0
# if I use for i in range(len(coin_list)), it returns an error message saying that index is out of range
for coinlist_index in range(len(coin_list)):
ways += make_change((n - coin_list[coinlist_index]), coinlist_index)
coinlist_index += 1
return ways
make_change(4)
Output: 5
My output was 5 (different ways to make change for 4 cents with 1 and 2-cent coins), instead of 3 (which is what I want).
I'm sure it has to do with the for loop toward the end, but when i change "for coinlist_index in range..." to a different iterator, i, I get an error that says index is out of range.
What is going on, and more importantly, how can I fix it?
EDIT: P.S. This is just a simple example that I'm working through to solve the actual assignment - Which is with 6 types of coins, in cents, (1, 5, 10, 25, 50, 100), and calculate how many ways to make change for 200 dollars. I have seen and tried the dynamic programming method out there, which worked, but we have to use recursion for assignment purposes.
Looks like I got it working. In each recursive pass you want to make sure that you aren't double counting possible ways to make the change. My thought to do this was to make sure that you never go backwards in the coin_list. So for the coin_list [1,2] if we ever use the 2 cent coin we never want the option to use the 1 cent coin afterwards. I made sure it follows this order by changing your for loop a bit:
for i in range(len(coin_list)-coinlist_index):
ways += make_change((n - coin_list[i+coinlist_index-1]), coinlist_index)
In the for loop I subtracted coinlist_index from the upper bound so we don't cycle over all coins once the index reaches 1, then added the index to where you pull from the coin_list, making sure once coinlist_index is 1 or more, we NEVER usecoin_list[0]. This got me to 3 in your sample case, hopefully it works for all cases. Full code:
def make_change(n, coinlist_index=None):
coin_list = [1, 2]
if coinlist_index == None:
coinlist_index = 0
#coin index position in coin_list; starts at index 0 and cycles through all the coins
if n == 0:
return 1
if n < 0:
return 0
ways = 0
# if I use for i in range(len(coin_list)), it returns an error message saying that index is out of range
for i in range(len(coin_list)-coinlist_index):
ways += make_change((n - coin_list[i+coinlist_index-1]), coinlist_index)
coinlist_index += 1
return ways
print(make_change(4))
I feel 5 is actually the correct answer.
1 1 1 1
1 1 2
1 2 1
2 1 1
2 2
Or if you want distinct result, you may store results in the list and remove the duplicate result.
def make_change(n, coinlist_index=0):
coin_list = [1, 2]
if n == 0:
return [[]]
if n < 0:
return []
ways = []
for coinlist_index in range(len(coin_list)):
res = make_change((n - coin_list[coinlist_index]), coinlist_index)
ways += list(map(lambda x : x + [coin_list[coinlist_index]], res))
return ways
def remove_dup(lolist):
res = []
for lst in lolist:
lst.sort()
if lst not in res:
res.append(lst)
return res
print remove_dup(make_change(4))
Need to remove every third element and return it once the list has only two elements left
def duck_duck_goose(lst: List[str]) -> List[str]:
"""Given an list of names (strings), play 'duck duck goose' with it,
knocking out every third name (wrapping around) until only two names are
left. In other words, when you hit the end of the list, wrap around and keep
counting from where you were.
For example, if given this list ['Nathan', 'Sasha', 'Sara', 'Jennie'], you'd
first knock out Sara. Then first 'duck' on Jennie, wrap around to 'duck' on
Nathan and 'goose' on Sasha - knocking him out and leaving only Nathan and
Jennie.
You may assume the list has 3+ names to start
Args:
lst - a list of names (strings)
Returns:
the resulting list after playing duck duck goose
"""
raise NotImplementedError("duck_duck_goose")
names = ["sasha", "nathan", "jennie", "shane", "will", "sara"]
assert duck_duck_goose(names) == ["sasha", "will"]
Here's a short snippet on how you can do it,
names = ["sasha", "nathan", "jennie", "shane", "will", "sara"]
def removeThirdName(names):
pos = 3 - 1
index = 0
len_list = (len(names))
while len_list > 2:
index = (pos + index) % len_list
print(names.pop(index))
len_list -= 1
removeThirdName(names)
print(names)
Outputs:
['sasha', 'will']
I've looked through all the examples in here already of this and nothing quite answers my question. I'm very new to Groovy.
I want to create something like a list or an array of floating point numbers, prices such as 239.99.
I then want to pass that array or list to a method that will determine the median price in that array or list of numbers. The total size will vary.
Is there any quick and easy code to do this? How do I add each number to the array or list and must I use doubles?
Any help is appreciated, this one has me stuck and frustrated.
Thanks!
The following function determines the median for non-empty lists.
def median(data) {
def copy = data.toSorted()
def middle = data.size().intdiv(2)
// you can omit the return in groovy for the last statement
data.size() % 2 ? copy[middle] : (copy[middle - 1] + copy[middle]) / 2
}
It works with all types that support addition and division.
For example:
assert median([1, 7, 4, 3]) == 3.5
assert median([1, 7, 4]) == 4
assert median([1, 7]) == 4
assert median([1]) == 1
assert median([1.7, 3.4, 10.9, 4.2]) == 3.8
In terms of what you can do with lists check the Lists overview and then the List API.
Imagine four railroad cars positioned on the input side of the track in the figure above, numbered 1, 2, 3, and 4, respectively. Suppose we perform the following sequence of operations (which is compatible with the direction of the arrows in the diagram and does not require cars to "jump over" other cars):
As a result of these operations the original order of the cars, 1234, has been changed into 2431.
The operations above can be more concisely described by the code SSXSSXXX, where S stands for move a car from the input into the stack, and X stands for move a car from the stack into the output. Some sequences of S's and X's specify meaningless operations, since there may be no cars available on the specified track; for example, the sequence SXXSSXXS cannot be carried out. (Try it to see why.)
Write and test a function that emulates the train car switching:
# [import statements]
import q2_fun
# [constants]
# [rest of program code]
cars = [1, 2, 3, 4]
s_x = input("enter a code with s's and x's to move one stack to another")
list1 = q2_fun.train_swicth(cars, s_x)
print(list1)
from stack_array import Stack
def train_swicth(cars, s_x):
s = Stack()
list1 = []
for i in range(len(s_x)):
if s_x[i] == "s":
a = s_x.append()
s.push(a)
elif s_x[i] == "x":
b = s.pop()
list1.append(b)
return list1
I keep getting [] as the return and it should be 2431 with ssxssxxx. Can I get some help?
if I understood you right you could do:
def train_swicth(cars, s_x):
i=0
s=[]
out=[]
for c in s_x:
if c=="s":
s.append(cars[i])
i+=1
elif c=="x":
out.append(s.pop())
return out
as lists can be used as stacks with append as push-operation