i want to create a nontransitiv dice game
A = [3, 5, 7]
B = [2, 4, 9]
C = [1, 6, 8]
choice1 = input("Chose a Dice (A/B/C)")
result1 = random.choice(choice1)
The user will enter a string like "A" and i want it to become the variable A so that the random.choice function will output a random number from the corresponding list
You could create a dictionary with the letters as keys and the arrays as values. Then, whatever the user puts, key into the dictionary.
diceDict = {
"A": [3, 5, 7],
"B": [2, 4, 9],
"C": [1, 6, 8]
}
result = random.choice(diceDict[choice1])
I don't know what language this is written in but you need to perform some sort of check on the user entered value.... e.g
(pseudocode)
if (choice1 === "A") getRandomFromArray(A)
if (choice1 === "B") getRandomFromArray(B)
.... etc...
I am new in dynamic programming..
This is a python code for finding shortest combination of numbers that add up to exactly the target sum using memoization.
global memo
memo={}
def bestSum(targetSum,arr):
if targetSum in memo:
return memo[targetSum]
#Base conditions
if targetSum==0:
return []
if targetSum<0:
return None
# Branching statments
shortestCombination=None
for i in arr:
remainder_combination=bestSum(targetSum-i,arr)
if remainder_combination != None:
combination=remainder_combination
combination.append(i)
if shortestCombination ==None or len(shortestCombination)>len(combination):
shortestCombination=combination
memo[targetSum]=shortestCombination
return shortestCombination
print(bestSum(10,[1,4,5]))
But the output was this
[4, 1, 4, 1, 5, 1]
whereas the correct output is
[5,5]
if i comment the memoization statements the output will be correct..
This is the python code without memoization for the same problem...
# global memo
# memo={}
def bestSum(targetSum,arr):
# if targetSum in memo:
# return memo[targetSum]
#Base conditions
if targetSum==0:
return []
if targetSum<0:
return None
# Branching statments
shortestCombination=None
for i in arr:
remainder_combination=bestSum(targetSum-i,arr)
if remainder_combination != None:
combination=remainder_combination
combination.append(i)
if shortestCombination ==None or len(shortestCombination)>len(combination):
shortestCombination=combination
# memo[targetSum]=shortestCombination
return shortestCombination
print(bestSum(10,[1,4,5]))
The above code gave me the correct output.
The correct output is also obtained in java script for the same problem with memoization by using object
const bestSum=(targetSum,numbers,memo={})=>{
if(targetSum in memo) return memo[targetSum];
if(targetSum===0) return [];
if(targetSum<0) return null;
let shortestCombination =null;
for (let num of numbers){
reminderCombination=bestSum(targetSum-num,numbers,memo);
if(reminderCombination !==null){
const combination=[...reminderCombination,num]
if(shortestCombination===null || combination.length< shortestCombination.length){
shortestCombination=combination
}
}
}
memo[targetSum]=shortestCombination
return shortestCombination
};
console.log(bestSum(10,[1,4,5]))
Few more examples
print(bestSum(7,[3,4,7]))
print(bestSum(20,[1,2,3,4,5,10]))
print(bestSum(3,[3,2,1]))
Correct outputs
[7]
[10, 10]
[3]
Wrong outputs when memoization is used
[7]
[10, 1, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 5, 10]
[3, 4, 2, 3, 5, 10, 1, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 5]
Thank you!
We have to use copy() method in order to copy a list, without using it we are referencing the list not coping.
memo={}
def bestSum(targetSum,arr):
if targetSum in memo:
return memo[targetSum]
if targetSum==0:
return []
if targetSum<0:
return None
shortestCombination=None
for i in arr:
remainder_combination=bestSum(targetSum-i,arr)
if remainder_combination != None:
combination = remainder_combination.copy()
combination.append(i)
if shortestCombination ==None or len(shortestCombination)>len(combination):
shortestCombination=combination.copy()
memo[targetSum]=shortestCombination
return shortestCombination
print(bestSum(10,[1,4,5]))
I have the following Python dict:
[(2, [3, 4, 5]), (3, [1, 0, 0, 0, 1]), (4, [-1]), (10, [1, 2, 3])]
Now I want to sort them on the basis of sum of values of the values of dictionary, so for the first key the sum of values is 3+4+5=12.
I have written the following code that does the job:
def myComparator(a,b):
print "Values(a,b): ",(a,b)
sum_a=sum(a[1])
sum_b=sum(b[1])
print sum_a,sum_b
print "Comparision Returns:",cmp(sum_a,sum_b)
return cmp(sum_a,sum_b)
items.sort(myComparator)
print items
This is what the output that I get after running above:
Values(a,b): ((3, [1, 0, 0, 0, 1]), (2, [3, 4, 5]))
2 12
Comparision Returns: -1
Values(a,b): ((4, [-1]), (3, [1, 0, 0, 0, 1]))
-1 2
Comparision Returns: -1
Values(a,b): ((10, [1, 2, 3]), (4, [-1]))
6 -1
Comparision Returns: 1
Values(a,b): ((10, [1, 2, 3]), (3, [1, 0, 0, 0, 1]))
6 2
Comparision Returns: 1
Values(a,b): ((10, [1, 2, 3]), (2, [3, 4, 5]))
6 12
Comparision Returns: -1
[(4, [-1]), (3, [1, 0, 0, 0, 1]), (10, [1, 2, 3]), (2, [3, 4, 5])]
Now I am unable to understand as to how the comparator is working, which two values are being passed and how many such comparisons would happen? Is it creating a sorted list of keys internally where it keeps track of each comparison made? Also the behavior seems to be very random. I am confused, any help would be appreciated.
The number and which comparisons are done is not documented and in fact, it can freely change from different implementations. The only guarantee is that if the comparison function makes sense the method will sort the list.
CPython uses the Timsort algorithm to sort lists, so what you see is the order in which that algorithm is performing the comparisons (if I'm not mistaken for very short lists Timsort just uses insertion sort)
Python is not keeping track of "keys". It just calls your comparison function every time a comparison is made. So your function can be called many more than len(items) times.
If you want to use keys you should use the key argument. In fact you could do:
items.sort(key=lambda x: sum(x[1]))
This will create the keys and then sort using the usual comparison operator on the keys. This is guaranteed to call the function passed by key only len(items) times.
Given that your list is:
[a,b,c,d]
The sequence of comparisons you are seeing is:
b < a # -1 true --> [b, a, c, d]
c < b # -1 true --> [c, b, a, d]
d < c # 1 false
d < b # 1 false
d < a # -1 true --> [c, b, d, a]
how the comparator is working
This is well documented:
Compare the two objects x and y and return an integer according to the outcome. The return value is negative if x < y, zero if x == y and strictly positive if x > y.
Instead of calling the cmp function you could have written:
sum_a=sum(a[1])
sum_b=sum(b[1])
if sum_a < sum_b:
return -1
elif sum_a == sum_b:
return 0
else:
return 1
which two values are being passed
From your print statements you can see the two values that are passed. Let's look at the first iteration:
((3, [1, 0, 0, 0, 1]), (2, [3, 4, 5]))
What you are printing here is a tuple (a, b), so the actual values passed into your comparison functions are
a = (3, [1, 0, 0, 0, 1])
b = (2, [3, 4, 5]))
By means of your function, you then compare the sum of the two lists in each tuple, which you denote sum_a and sum_b in your code.
and how many such comparisons would happen?
I guess what you are really asking: How does the sort work, by just calling a single function?
The short answer is: it uses the Timsort algorithm, and it calls the comparison function O(n * log n) times (note that the actual number of calls is c * n * log n, where c > 0).
To understand what is happening, picture yourself sorting a list of values, say v = [4,2,6,3]. If you go about this systematically, you might do this:
start at the first value, at index i = 0
compare v[i] with v[i+1]
If v[i+1] < v[i], swap them
increase i, repeat from 2 until i == len(v) - 2
start at 1 until no further swaps occurred
So you get, i =
0: 2 < 4 => [2, 4, 6, 3] (swap)
1: 6 < 4 => [2, 4, 6, 3] (no swap)
2: 3 < 6 => [2, 4, 3, 6] (swap)
Start again:
0: 4 < 2 => [2, 4, 3, 6] (no swap)
1: 3 < 4 => [2, 3, 4, 6] (swap)
2: 6 < 4 => [2, 3, 4, 6] (no swap)
Start again - there will be no further swaps, so stop. Your list is sorted. In this example we have run through the list 3 times, and there were 3 * 3 = 9 comparisons.
Obviously this is not very efficient -- the sort() method only calls your comparator function 5 times. The reason is that it employs a more efficient sort algorithm than the simple one explained above.
Also the behavior seems to be very random.
Note that the sequence of values passed to your comparator function is not, in general, defined. However, the sort function does all the necessary comparisons between any two values of the iterable it receives.
Is it creating a sorted list of keys internally where it keeps track of each comparison made?
No, it is not keeping a list of keys internally. Rather the sorting algorithm essentially iterates over the list you give it. In fact it builds subsets of lists to avoid doing too many comparisons - there is a nice visualization of how the sorting algorithm works at Visualising Sorting Algorithms: Python's timsort by Aldo Cortesi
Basically, for the simple list such as [2, 4, 6, 3, 1] and the complex list you provided, the sorting algorithms are the same.
The only differences are the complexity of elements in the list and the comparing scheme that how to compare any tow elements (e.g. myComparator you provided).
There is a good description for Python Sorting: https://wiki.python.org/moin/HowTo/Sorting
First, the cmp() function:
cmp(...)
cmp(x, y) -> integer
Return negative if x<y, zero if x==y, positive if x>y.
You are using this line: items.sort(myComparator) which is equivalent to saying: items.sort(-1) or items.sort(0) or items.sort(1)
Since you want to sort based on the sum of each tuples list, you could do this:
mylist = [(2, [3, 4, 5]), (3, [1, 0, 0, 0, 1]), (4, [-1]), (10, [1, 2, 3])]
sorted(mylist, key=lambda pair: sum(pair[1]))
What this is doing is, I think, exactly what you wanted. Sorting mylist based on the sum() of each tuples list
I need to sort by source value size() descending:
def source =
[(firstString): [3, 2, 1],
(secondString): [3, 2, 1, 4],
(thirdString): [3]]
expected:
[(secondString): [3, 2, 1, 4],
(firstString): [3, 2, 1],
(thirdString): [3]]
I've tried to sort doing this:
source.sort { -it.value.size() }
How can I achieve this?
The following is the working code for your expected result:
def source = [
"(firstString)": [3, 2, 1],
"(secondString)": [3, 2, 1, 4],
"(thirdString)": [3]
]
def sortedResult = source.sort { -it.value.size()}
println sortedResult
Working example here on groovy console : https://groovyconsole.appspot.com/script/5104124974596096
The sort that takes a Closure as an argument does not mutate the original Map. It only returns a new map, so you need to assign it (you can assign it to itself).
source = source.sort { -it.value.size() }
With Collections, there is another type of sort that takes a Boolean as well as a Closure. In this case, the Boolean indicates whether you want to mutate the original Collection or just return a new Collection.
a = [1,3,2]
a.sort (true) { it }
assert a = [1,2,3]
This doesn't apply to Map. So use the assignment syntax above.
Let's say I've got a list of numbers:
def list = [1, 2, 3, 4, 5]
I want to separate it into two groups - odd and even numbers.
I am doing it like this:
def map = list.groupBy { it % 2 == 1 }
The resulting map looks like this
[true:[1, 3, 5], false:[2, 4, 6]]
But how to set my custom key for odd and even values instead of having true and false?
Here you are:
def list = [1, 2, 3, 4, 5, 6, ]
def map = list.groupBy { it % 2 ? 'odd' : 'even' }