how to sort map based on keys - sorting

I have the following map:
MyVals {12 -3, 24 -9, 36 -777, 48 -3037, 180 0, 360 0, 240 0, 120 0, 0 0, 144 0, 3 0, 6 -1, 9 -1, 108 0, 60 0, 72 0, 84 0, 96 0}
I am removing zero values then I need to sort it by the key
MyValsZeroRemoved(apply merge (for [[k v] MyVals :when (not (= 0 v))] {k v}))
Which returns:
MyValsZeroRemoved {9 -1, 6 -1, 48 -3037, 36 -777, 24 -9, 12 -3}
Then I sort it:
MyValsZeroRemovedSorted(sort MyValsZeroRemoved)
but that results in
([12 -3] [24 -9] [36 -777] [48 -3037] [6 -1] [9 -1])
How do I sort the map to get the desired output as below:
([6 -1] [9 -1] [12 -3] [24 -9] [36 -777] [48 -3037])

The only way you get that sort order is if you did
(sort-by (comp str first) {9 7, 6 5, 3 3, 0 -1, 36 4670, 24 3203, 12 23})
;=> ([0 -1] [12 23] [24 3203] [3 3] [36 4670] [6 5] [9 7])
That will sort them as strings. If you need to sort a map by key literals then regular sort works
(sort {9 7, 6 5, 3 3, 0 -1, 36 4670, 24 3203, 12 23})
;=> ([0 -1] [3 3] [6 5] [9 7] [12 23] [24 3203] [36 4670])
If you need to sort by the value or if you need to convert the key or value then you should use sort-by and a function to extract the value to perform the conversion.
(sort-by second {9 7, 6 5, 3 3, 0 -1, 36 4670, 24 3203, 12 23})
;=> ([0 -1] [3 3] [6 5] [9 7] [12 23] [24 3203] [36 4670])

The sort function will give the output you want.
user> (sort {9 7, 6 5, 3 3, 0 -1, 36 4670, 24 3203, 12 23})
([0 -1] [3 3] [6 5] [9 7] [12 23] [24 3203] [36 4670])

Related

Golang slice append exception

This is a leet code problem, and when I try to answer with the code blew:
package main
import "fmt"
func main() {
nums := []int{9, 0, 3, 5, 7}
fmt.Println(subsets(nums))
}
func subsets(nums []int) [][]int {
var result [][]int
result = append(result, []int{})
for _, v := range(nums) {
for _, rv := range(result) {
result = append(result, append(rv, v))
}
}
return result
}
Leetcode told me wrong answer:
Wrong Answer
Details
Input
[9,0,3,5,7]
Output
[[],[9],[0],[9,0],[3],[9,3],[0,3],[9,0,3],[5],[9,5],[0,5],[9,0,5],[3,5],[9,3,5],[0,3,5],[9,0,3,7],[7],[9,7],[0,7],[9,0,7],[3,7],[9,3,7],[0,3,7],[9,0,3,7],[5,7],[9,5,7],[0,5,7],[9,0,5,7],[3,5,7],[9,3,5,7],[0,3,5,7],[9,0,3,7,7]]
Expected
[[],[9],[0],[0,9],[3],[3,9],[0,3],[0,3,9],[5],[5,9],[0,5],[0,5,9],[3,5],[3,5,9],[0,3,5],[0,3,5,9],[7],[7,9],[0,7],[0,7,9],[3,7],[3,7,9],[0,3,7],[0,3,7,9],[5,7],[5,7,9],[0,5,7],[0,5,7,9],[3,5,7],[3,5,7,9],[0,3,5,7],[0,3,5,7,9]]
The output slice index 15, it should be [9,0,3,5] like the expected, but the result is [9,0,3,7].
So I try to run this code by go playgroud online,the answer is the same wrong, and then I run this code in goland with debug mode,I find when I make the slice append([9,0,3], 7), the output slice index 15 change at the same time.
My local go env: go version go1.17.6 windows/amd64
I'm just a beginner to golang, could anyone explain this situation?
Thank you very much.
ps: I try to use blew code to recover same issue, but I failed.
package main
import "fmt"
func main() {
a := [][]int{{}, {9}, {0}, {9, 0}, {3}, {9, 3}, {0, 3}, {9, 0, 3}, {5}, {9, 5}, {0, 5}, {9, 0, 5}, {3, 5}, {9, 3, 5}, {0, 3, 5}, {9, 0, 3, 5}}
i := 7
for _, v := range a {
// fmt.Println(a)
a = append(a, append(v, i))
// fmt.Println(a)
}
fmt.Println(a)
}
result:
[[] [9] [0] [9 0] [3] [9 3] [0 3] [9 0 3] [5] [9 5] [0 5] [9 0 5] [3 5] [9 3 5] [0 3 5] [9 0 3 5] [7] [9 7] [0 7] [9 0 7] [3 7] [9 3 7] [0 3 7] [9 0 3 7] [5 7] [9 5 7] [0 5 7] [9 0 5 7] [3 5 7] [9 3 5 7] [0 3 5 7] [9 0 3 5 7]]
You are reusing the same backing array in some of your slices, because that's what append does if there's capacity remaining. A simple fix is to replace append(rv, v) with append(append([]int{}, rv...), v), creating an entirely new slice. An alternative is to force the append to allocate a fresh backing array by capping the slice to its current length: append(rv[:len(rv):len(rv)], v).
Playground link with working code: https://go.dev/play/p/Gc-yF5KQOAO

How to visualize a 3-way mergesort?

[6, 4, 3, 7, 2, 9, 1, 5]
[6, 4], [3, 7, 2], [9, 1, 5]
[6, 4], [3], [7], [2], [9], [1], [5]
swap
[6, 4], [3], [7], [2], [9], [1], [5]
[4, 6], [2, 3, 7], [1, 5, 9]
[2, 3, 4, 6, 7], [1, 5, 9]
[1, 2, 3, 4, 5, 6, 7, 9]
Is this correct? And why is this n log base 3 n?
The merge operations should be 3 way:
[6] [4] [3] [7] [2] [9] [1] [5]
[3 4 6] [2 7 9] [1 5]
[1 2 3 4 5 6 7 9]
|N|J|H|Q|6|L|K|5|P|E|3|A|G|8|D|4|O|I|B|0|9|M|F|2|1|C|7|
|H J N|6 L Q|5 K P|3 A E|8 D G|4 I O|0 9 B|2 F M|1 7 C|
|5 6 H J K L N P Q|3 4 8 A D E G I O|0 1 2 7 9 B C F M|
|0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q|

How do I write Ruby's each_cons in Clojure?

How can I rewrite this Ruby code in Clojure?
seq = [1, 2, 3, 4, 5].each_cons(2)
#=> lazy Enumerable of pairs
seq.to_a
=> [[1, 2], [2, 3], [3, 4], [4, 5]]
Clojure:
(??? 2 [1 2 3 4 5])
;=> lazy seq of [1 2] [2 3] [3 4] [4 5]
What you are asking for is called sliding window over a lazy sequence.This way you can achieve that
user=> (partition 2 1 [1 2 3 4 5])
((1 2) (2 3) (3 4) (4 5))

Algorithm to distribute according to weights, with unknown total of items, guaranteeing good distribution?

I want to distribute tokens into 3 slots.
Each slot has some weight: maybe 50% of tokens should go into the first slot, 30% should go into the second slot, 20% into the third slot.
I don't know the total number of tokens – they keep on coming. I may get 1000 tokens to distribute at noon, I get another 300 at 1 p.m. and so on, unpredictably. At any point in time, the tokens I have received so far should be distributed as well as possible according to the weights.
One solution is to distribute by probabilities. I roll a 100-sided die for each token. If the result is 1–50, the token goes in slot 1. A result of 51–80 mean slot 2, a result of 81–100 mean slot 3.
But this means that it's not impossible (only improbable) that every single token ends up in slot 3, for example.
I want to guarantee that when I've received a total of 100 tokens, then exactly 50 of them will be in slot 1. When I've received 1000 tokens, exactly 500 should be in slot 1.
What is a good algorithm for this?
Calculate the error in each slot according to what the ideal distribution is. Always insert a token into the slot with the most error. If two or more slots are tied, insert into a random one among them.
The error is the difference between the expected number of tokens (tokens added * ratio) and the actual number of tokens.
This way you will always minimize error, and there will be no error if the tokens are able to be distributed exactly.
Demonstration code (this inserts into the first slot if there is equal amount of error instead of distributing randomly):
import random
tokens_in_slots = [0, 0, 0]
slot_distributions = [0.5, 0.3, 0.2]
def add_token():
num_tokens = sum(tokens_in_slots)
if not num_tokens:
#first token can go anywhere
tokens_in_slots[random.randint(0,2)] += 1
return
expected_tokens = [num_tokens*distr for distr in slot_distributions]
errors = [expected - actual
for expected, actual in zip(expected_tokens, tokens_in_slots)]
most_error = max(enumerate(errors), key=lambda (i,e): e)
tokens_in_slots[most_error[0]] += 1
def add_and_print(n):
for i in xrange(n):
add_token()
print sum(tokens_in_slots), tokens_in_slots
Result:
>>> add_and_print(100)
1 [0, 0, 1]
2 [1, 0, 1]
3 [1, 1, 1]
4 [2, 1, 1]
5 [2, 2, 1]
6 [3, 2, 1]
7 [3, 2, 2]
8 [4, 2, 2]
9 [4, 3, 2]
10 [5, 3, 2]
11 [6, 3, 2]
12 [6, 4, 2]
13 [6, 4, 3]
14 [7, 4, 3]
15 [7, 5, 3]
16 [8, 5, 3]
17 [8, 5, 4]
18 [9, 5, 4]
19 [9, 6, 4]
20 [10, 6, 4]
21 [11, 6, 4]
22 [11, 7, 4]
23 [11, 7, 5]
24 [12, 7, 5]
25 [12, 8, 5]
26 [13, 8, 5]
27 [13, 8, 6]
28 [14, 8, 6]
29 [14, 9, 6]
30 [15, 9, 6]
31 [16, 9, 6]
32 [16, 10, 6]
33 [16, 10, 7]
34 [17, 10, 7]
35 [17, 11, 7]
36 [18, 11, 7]
37 [18, 11, 8]
38 [19, 11, 8]
39 [19, 12, 8]
40 [20, 12, 8]
41 [21, 12, 8]
42 [21, 13, 8]
43 [21, 13, 9]
44 [22, 13, 9]
45 [22, 14, 9]
46 [23, 14, 9]
47 [23, 14, 10]
48 [24, 14, 10]
49 [24, 15, 10]
50 [25, 15, 10]
51 [26, 15, 10]
52 [26, 16, 10]
53 [26, 16, 11]
54 [27, 16, 11]
55 [27, 17, 11]
56 [28, 17, 11]
57 [28, 17, 12]
58 [29, 17, 12]
59 [29, 18, 12]
60 [30, 18, 12]
61 [31, 18, 12]
62 [31, 19, 12]
63 [31, 19, 13]
64 [32, 19, 13]
65 [32, 20, 13]
66 [33, 20, 13]
67 [33, 20, 14]
68 [34, 20, 14]
69 [34, 21, 14]
70 [35, 21, 14]
71 [36, 21, 14]
72 [36, 22, 14]
73 [36, 22, 15]
74 [37, 22, 15]
75 [37, 23, 15]
76 [38, 23, 15]
77 [38, 23, 16]
78 [39, 23, 16]
79 [39, 24, 16]
80 [40, 24, 16]
81 [41, 24, 16]
82 [41, 25, 16]
83 [41, 25, 17]
84 [42, 25, 17]
85 [42, 26, 17]
86 [43, 26, 17]
87 [43, 26, 18]
88 [44, 26, 18]
89 [44, 27, 18]
90 [45, 27, 18]
91 [46, 27, 18]
92 [46, 28, 18]
93 [46, 28, 19]
94 [47, 28, 19]
95 [47, 29, 19]
96 [48, 29, 19]
97 [48, 29, 20]
98 [49, 29, 20]
99 [49, 30, 20]
100 [50, 30, 20]
Results for
tokens_in_slots = [0, 0, 0, 0]
slot_distributions = [0.8, 0.1, 0.05, 0.05]
:
>>> add_and_print(100)
1 [0, 0, 1, 0]
2 [1, 0, 1, 0]
3 [2, 0, 1, 0]
4 [3, 0, 1, 0]
5 [3, 1, 1, 0]
6 [4, 1, 1, 0]
7 [5, 1, 1, 0]
8 [6, 1, 1, 0]
9 [7, 1, 1, 0]
10 [7, 1, 1, 1]
11 [8, 1, 1, 1]
12 [9, 1, 1, 1]
13 [10, 1, 1, 1]
14 [11, 1, 1, 1]
15 [11, 2, 1, 1]
16 [12, 2, 1, 1]
17 [13, 2, 1, 1]
18 [14, 2, 1, 1]
19 [15, 2, 1, 1]
20 [16, 2, 1, 1]
21 [17, 2, 1, 1]
22 [17, 3, 1, 1]
23 [18, 3, 1, 1]
24 [19, 3, 1, 1]
25 [20, 3, 1, 1]
26 [20, 3, 2, 1]
27 [21, 3, 2, 1]
28 [22, 3, 2, 1]
29 [23, 3, 2, 1]
30 [23, 3, 2, 2]
31 [24, 3, 2, 2]
32 [25, 3, 2, 2]
33 [26, 3, 2, 2]
34 [27, 3, 2, 2]
35 [27, 4, 2, 2]
36 [28, 4, 2, 2]
37 [29, 4, 2, 2]
38 [30, 4, 2, 2]
39 [31, 4, 2, 2]
40 [32, 4, 2, 2]
41 [33, 4, 2, 2]
42 [33, 5, 2, 2]
43 [34, 5, 2, 2]
44 [35, 5, 2, 2]
45 [36, 5, 2, 2]
46 [36, 5, 3, 2]
47 [37, 5, 3, 2]
48 [38, 5, 3, 2]
49 [39, 5, 3, 2]
50 [39, 5, 3, 3]
51 [40, 5, 3, 3]
52 [41, 5, 3, 3]
53 [42, 5, 3, 3]
54 [43, 5, 3, 3]
55 [43, 6, 3, 3]
56 [44, 6, 3, 3]
57 [45, 6, 3, 3]
58 [46, 6, 3, 3]
59 [47, 6, 3, 3]
60 [48, 6, 3, 3]
61 [49, 6, 3, 3]
62 [49, 7, 3, 3]
63 [50, 7, 3, 3]
64 [51, 7, 3, 3]
65 [52, 7, 3, 3]
66 [52, 7, 4, 3]
67 [53, 7, 4, 3]
68 [54, 7, 4, 3]
69 [55, 7, 4, 3]
70 [55, 7, 4, 4]
71 [56, 7, 4, 4]
72 [57, 7, 4, 4]
73 [58, 7, 4, 4]
74 [59, 7, 4, 4]
75 [59, 8, 4, 4]
76 [60, 8, 4, 4]
77 [61, 8, 4, 4]
78 [62, 8, 4, 4]
79 [63, 8, 4, 4]
80 [64, 8, 4, 4]
81 [65, 8, 4, 4]
82 [65, 9, 4, 4]
83 [66, 9, 4, 4]
84 [67, 9, 4, 4]
85 [68, 9, 4, 4]
86 [68, 9, 5, 4]
87 [69, 9, 5, 4]
88 [70, 9, 5, 4]
89 [71, 9, 5, 4]
90 [71, 9, 5, 5]
91 [72, 9, 5, 5]
92 [73, 9, 5, 5]
93 [74, 9, 5, 5]
94 [75, 9, 5, 5]
95 [75, 10, 5, 5]
96 [76, 10, 5, 5]
97 [77, 10, 5, 5]
98 [78, 10, 5, 5]
99 [79, 10, 5, 5]
100 [80, 10, 5, 5]
The solution that springs to my mind:
Give every slot a computed score. Put the token in the slot with the highest score. If more than one share that score, I don't care whether we pick the first one or a random one.
The computed score would be calculated something like the following Ruby/pseudo-code:
# Example values
# Floats to avoid integer division
slot_1_weight = 50.0
total_weight = 100.0
slot_1_tokens = 2.0
total_tokens = 3.0
if total_tokens == 0 || total_weight == 0 || slot_1_tokens
# Avoid division by zero.
slot_1_score = slot_1_weight
else
expected_distribution = slot_1_weight/total_weight
actual_distribution = slot_1_tokens/total_tokens
slot_1_score = slot_1_weight * (expected_distribution/actual_distribution)
end
So when expected and actual match, the score is the original weight. If expected is too high, the weight is scaled down. If expected is too low, the weight is scaled up.

Numpy sorting help

In Numpy, how do I create an array of indices which can be used return the values of the source array in sorted order? eg:
Source:
[[4 2 6 7]
[1 4 8 9]
[3 1 0 3]]
Indices:
[10 4 9 1 8 11 0 5 2 3 6 7]
Take a look at numpy.argsort - it will return the indices that would sort your array. You can also specifiy the axis along which to sort. Try:
a = numpy.asarray([[4, 2, 6, 7], [1, 4, 8, 9], [3, 1, 0, 3]])
numpy.argsort(a.flat)
>> array([10, 4, 9, 1, 8, 11, 0, 5, 2, 3, 6, 7])
The answer's in the manual:
src = [[ ... ]]
ravel_src = np.ravel(src)
indices = np.argsort(ra)

Resources