How to sorting (ASCENDING) by key using Python dictionary - sorting

I have several dictionary
{
('ABD12-GOU10', 'ASS 4W LINE 3'):[15,5],
('ABD13-GOU11', 'ASS 4W LINE 1'):[7,5],
('ABD13-GOU11', 'ASS 4W LINE 1'):[22,5],
('ABD14-GOU13', 'ASS 4W LINE 1'):[12,5],
('ABD14-GOU19', 'ASS 4W LINE 2'):[4,5],
('ABD14-GOU10', 'ASS 4W LINE 3'):[2,5],
('ABD14-GOU13', 'ASS 4W LINE 4'):[18,5],
('ABD14-GOU12', 'ASS 4W LINE 5'):[9,5],
('ABD14-GOU11', 'ASS 4W LINE 6'):[3,5],
}
How to sorting by key 2 ex: ASS 4W LINE 1 and sorting by key 1 ex: ABD12-GOu10. I want like this:
{
('ABD13-GOU11', 'ASS 4W LINE 1'):[7,5],
('ABD13-GOU11', 'ASS 4W LINE 1'):[22,5],
('ABD14-GOU13', 'ASS 4W LINE 1'):[12,5],
('ABD14-GOU19', 'ASS 4W LINE 2'):[4,5],
('ABD12-GOU10', 'ASS 4W LINE 3'):[15,5],
('ABD14-GOU10', 'ASS 4W LINE 3'):[2,5],
('ABD14-GOU13', 'ASS 4W LINE 4'):[18,5],
('ABD14-GOU12', 'ASS 4W LINE 5'):[9,5],
('ABD14-GOU11', 'ASS 4W LINE 6'):[3,5],
}

Keep in mind that Python dictkeep order since Python 3.6 only
I use numpy for argsorting, but you can use anything
You can do:
import numpy as np
keys = list(D.keys())
sorted_D = {
keys[i]: D[keys[i]] for i in np.argsort([k[1] for k in keys])
}
output:
{('ABD13-GOU11', 'ASS 4W LINE 1'): [22, 5],
('ABD14-GOU13', 'ASS 4W LINE 1'): [12, 5],
('ABD14-GOU19', 'ASS 4W LINE 2'): [4, 5],
('ABD12-GOU10', 'ASS 4W LINE 3'): [15, 5],
('ABD14-GOU10', 'ASS 4W LINE 3'): [2, 5],
('ABD14-GOU13', 'ASS 4W LINE 4'): [18, 5],
('ABD14-GOU12', 'ASS 4W LINE 5'): [9, 5],
('ABD14-GOU11', 'ASS 4W LINE 6'): [3, 5]}
However, this will only sort on index 1 of the key, so it might have different behaviours on dictionary with keys with same index 1 value.
EDIT:
As said in a comment, your original dictionary has identical keys, so the output above has not the same number of values

Related

Convert byte array to hex string

I am trying to convert the following byte array to hexadecimal;
[1, 1, 65, -50, 6, 104, -91, -70, -100, 119, -100, 123, 52, -109, -33, 45, -14, 86, -105, -97, -115, 16]
The result should be;
010141CE0668A5BA9C779C7B3493DF2DF256979F8D10
Here is my current attempt;
item.getProperties["Mapi-Conversation-Index"].to_a.map {|s| s.to_s(16)}.join()
But my output is: 010141-320668-5b-46-6477-647b34-6d-212d-e56-69-61-7310
arr = [1, 1, 65, -50, 6, 104, -91, -70, -100, 119, -100, 123, 52, -109, -33, 45, -14, 86]
arr.pack("c*").unpack("H*").first
#=> "010141ce0668a5ba9c779c7b3493df2df256"
See Array#pack and String#unpack.
The argument "c" for pack specifies an 8-bit signed integer. The argument "H" for unpack specifies "hex string (high nibble first)". The asterisk at the end of each directive specifies that "c" applies to all elements of arr and "H" applies to all characters of the string produced by pack.
Note that
arr.pack("c*")
#=> "\x01\x01A\xCE\x06h\xA5\xBA\x9Cw\x9C{4\x93\xDF-\xF2V"
and
arr.pack("c*").unpack("H*")
#=> ["010141ce0668a5ba9c779c7b3493df2df256"]
which is why first is needed to extract the string.
This works:
[1, 1, 65, -50].map { |n| '%02X' % (n & 0xFF) }.join
The %02X format specifier makes a 2-character-wide hex number, padded with 0 digits. The & 0xFF is necessary to convert your negative numbers into the standard 0 through 255 range that people usually use when talking about byte values.

How to extract frame types along with motion vectors using extract_mvs.c from ffmpeg

I have been researching ways to get frame types (I, P, B) along with the motion vector data returned from extract_mvs.c in the examples folder in ffmpeg.
The extract_mvs.c file after it is compiled, returns information like this:
framenum,source,blockw,blockh,srcx,srcy,dstx,dsty,flags
2,-1,16,16, 8, 8, 8, 8,0x0
2, 1,16,16, 8, 8, 8, 8,0x0
2, 1,16,16, 24, 8, 24, 8,0x0
2, 1,16,16, 40, 8, 40, 8,0x0
2, 1,16,16, 56, 8, 56, 8,0x0
2, 1,16,16, 72, 8, 72, 8,0x0
2, 1,16,16, 88, 8, 88, 8,0x0
...
297, 1,16,16, 248, 280, 248, 280,0x0
297, 1,16,16, 264, 280, 264, 280,0x0
297,-1,16,16, 278, 279, 280, 280,0x0
297, 1,16,16, 280, 280, 280, 280,0x0
297, 1,16,16, 296, 280, 296, 280,0x0
297, 1,16,16, 312, 280, 312, 280,0x0
297, 1,16,16, 328, 280, 328, 280,0x0
297, 1,16,16, 344, 280, 344, 280,0x0
Along with this information, I would like to output frame type so that I know framenum = 2 is, for example, a 'B' frame.
I tried different things, one of which was using a separate command:
ffprobe input.mp4 -show_frames | grep -E 'pict_type|coded_picture_number'
But the problem with this command is that it returns data like:
pict_type=I
coded_picture_number=0
pict_type=B
coded_picture_number=2
pict_type=P
coded_picture_number=1
pict_type=B
coded_picture_number=4
pict_type=P
coded_picture_number=3
....
pict_type=P
coded_picture_number=293
pict_type=B
coded_picture_number=297
pict_type=B
coded_picture_number=296
And there is no much I can relate here between coded_picture_number and framenum. The former starts counting from 0 and the later from 2. I assume framenum starting from 2, means the count from this variable is actually from 1, and it ignored 1 in the extraction process as it is maybe an I frame thus no motion vectors.
So, how can we use only extract_mvs.c to get not only that information it provides but also the frame types in the returned table. Any hints either syntax/command-wise or in editing the c file would be appreciated. Thanks in advance.
I found a way to get the frames, had posted on this question, where I replaced the flags argument with frametypes.

Generate numbers from n to m from a list

I'll start with an example; given n = 1 and m = 100 and a list [1, 2, 3]
generate all numbers with 1 digit and two digits and so on but they need to be less then 100 in this case.
Output:
- 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33
Then we stop because the next numbers will over 100, e.g:
- 111, 112, 113, 121, 122, 123, 131, 132, 133, 21..,. 22..., 23..., 31, 32, 33
As you noticed I am appending 1, 2, 3, 4 to a number created before, to do this I am using a recursive function, which is started in a for loop for each number in my list, and they it runs till the generated numbers are greater then my limit.
def x(str, finish, d, c)
return if d >= finish
[1, 2, 3, 4].each do |e|
x(str, end, d*c+e)
end
# do something if d >= str
end
This works fine if I need to start from 1, but if my starting number is a lot bigger, I still need to start to create this sequence.
Can somebody help me with a solution that will produce the same sequences, but from any starting point rather then 1, so if for example the starting point was 100 and end 200 the output will be:
111, 112, 113, 114, 121, 122, 123, 124, 131, 132, 132 [...]
A solution in any programming language would be nice, but please not builtin core libraries.
Code
def generate_em(minimum, maximum, list)
digits_min = minimum.to_s.size
digits_min += 1 if minimum > (list.max.to_s*digits_min).to_i
digits_max = maximum.to_s.size
digits_max -= 1 if maximum < (list.min.to_s*digits_max).to_i
(digits_min..digits_max).each_with_object([]) { |n,arr|
arr.concat(list.repeated_permutation(n).to_a.map { |a| a.join.to_i }) }.
uniq.
select { |n| (minimum..maximum).cover?(n) }
end
Examples
#1
minimum = 1
maximum = 100
list = [1, 2, 3]
generate_em(minimum, maximum, list)
#=> [1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33]
#2
minimum = 78
maximum = 3332
list = [3, 4, 5, 6, 7]
generate_em(minimum, maximum, list)
#=> [333, 334, 335, 336, 337, 343, 344, 345, 346, 347, 353, 354, 355, 356,
# 357, 363, 364, 365, 366, 367, 373, 374, 375, 376, 377, 433, 434, 435,
# 436, 437, 443, 444, 445, 446, 447, 453, 454, 455, 456, 457, 463, 464,
# 465, 466, 467, 473, 474, 475, 476, 477, 533, 534, 535, 536, 537, 543,
# 544, 545, 546, 547, 553, 554, 555, 556, 557, 563, 564, 565, 566, 567,
# 573, 574, 575, 576, 577, 633, 634, 635, 636, 637, 643, 644, 645, 646,
# 647, 653, 654, 655, 656, 657, 663, 664, 665, 666, 667, 673, 674, 675,
# 676, 677, 733, 734, 735, 736, 737, 743, 744, 745, 746, 747, 753, 754,
# 755, 756, 757, 763, 764, 765, 766, 767, 773, 774, 775, 776, 777]
#3
minimum = 0
maximum = 100
list = [0, 1, 2]
generate_em(minimum, maximum, list)
#=> [0, 1, 2, 10, 11, 12, 20, 21, 22, 100]
Explanation
Example #1
The steps for the first example above are as follows.
digits_min = minimum.to_s.size
#=> 1
Increase digits_min by one if mimimum is larger than the largest digits_min digits from list.
digits_min += 1 if minimum > (list.max.to_s*digits_min).to_i
digits_min
#=> 1
digits_max = maximum.to_s.size
#=> 3
Decrease digits_max by one if maximum is smaller than the smallest digits_max digits from list.
digits_max -= 1 if maximum < (list.min.to_s*digits_max).to_i
digits_max
#=> 2
We improve efficiency by having reduced digits_max from 3 to 2
c = digits_min..digits_max
#=> 1..2
d = c.each_with_object([])
#=> #<Enumerator: 1..2:each_with_object([])>
We can see the elements that will be generated by this enumerator by invoking Enumerable#entries (or Enumerable#to_a) on it.
d.entries
#=> [[1, []], [2, []]]
n, arr = d.next
#=> [1, []]
n #=> 1
arr
#=> []
e = list.permutation(n)
#=> #<Enumerator: [1, 2, 3]:permutation(2)>
f = e.to_a
#=> [[1], [2], [3]]
arr.concat f
#=> [[1], [2], [3]]
n, arr = d.next
#=> [2, [[1], [2], [3]]]
n #=> 2
arr
#=> [[1], [2], [3]]
e = list.permutation(n)
#=> #<Enumerator: [1, 2, 3]:permutation(2)>
f = e.to_a
#=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
arr.concat f
#=> [[1], [2], [3], [1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
arr is returned by each_with_object's block.
g = arr.map { |a| a.join.to_i }
#=> [1, 2, 3, 12, 13, 21, 23, 31, 32]
h = g.uniq
#=> [1, 2, 3, 12, 13, 21, 23, 31, 32]
h.select { |n| (minimum..maximum).cover?(n) }
#=> [1, 2, 3, 12, 13, 21, 23, 31, 32]
Example #2
In the second example no two-digit combinations are generated because
78 > (list.max.to_s*2).to_i
#=> 78 > 77 => true
and no four-digit combinations are generated because
3332 < (list.min.to_s*4).to_i
#=> 3332 < 3333 => true
Example #3
Without uniq, the method would have returned duplicate values:
[0, 1, 2, 0, 1, 2, 10, 11, 12, 20, 21, 22, 0, 1, 2, 10, 11, 12, 20, 21, 22, 100]
Since you wrote your example code in Ruby, you could use repeated_permutation :
def possible_numbers(arr, min, max)
min_digits = min.to_s.size
max_digits = max.to_s.size
(min_digits..max_digits).flat_map do |i|
arr.repeated_permutation(i)
.map { |digits| digits.join.to_i }
.select { |number| number >= min && number <= max }
.uniq
end
end
p possible_numbers([1, 2, 3], 100, 200)
# => [111, 112, 113, 121, 122, 123, 131, 132, 133]
So, this takes an input of the digits provided, makes all the digit combinations repeatedly until it reaches your max. You'll want to adjust them to include recovery and saves in the event non-integers are entered or if it's otherwise impossible to hit the max for some reason - but this is a solid framework.
digits = [1,2,3]
max = 100
def possible_numbers(arr, max)
loop do
arr.product(arr).each do |combo|
return arr.uniq if combo.join("").to_i > max
arr << combo.join("").to_i
end
end
end
possible_numbers(digits, max)
Output:
=> [1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33]
You can proceed from "right" (least significant digit) to "left" (most significant digit), keeping track of two values:
min, the least valid integer that has the same number of digits as what you've processed so far. So, for example, if you've processed a trailing 27, then the least valid two-digit integer is 11.
max, the least valid integer that has the same number of digits as what you've processed so far and is greater than or equal to what you've processed so far. So, for example, if you've processed a trailing 27, then the least valid two-digit integer greater than or equal to 27 is 31.
Note that max won't always exist. For example, there's no valid two-digit integer greater than or equal to 70.
The reason you need min is that if you encounter a digit that's not in your list of allowed digits, then the new max will incorporate the previous min instead of the previous max. (For example, the least valid two-digit integer greater than or equal to 02 is 11, not 12.)
At the end, you return max, if it exists; otherwise, you return min, but prepending the least digit from your list.
For example, if this.allowedDigits is a collection of allowed digits, then we can write (in Java):
private Integer getAllowedDigitGreaterThanOrEqualTo(final int digit) {
for (int result = digit; result < 10; ++result) {
if (this.allowedDigits.contains(result)) {
return result;
}
}
// digit is bigger than anything in the list:
return null;
}
private int getAllowedNumberGreaterThanOrEqualTo(int n) {
int minResult = 0;
Integer maxResult = 0;
int powerOfTen = 1;
while (n > 0) {
final int digit = n % 10;
n /= 10;
minResult = getAllowedDigitGreaterThanOrEqualTo(0) * powerOfTen + minResult;
if (maxResult != null && this.allowedDigits.contains(digit)) {
maxResult = digit * powerOfTen + maxResult;
} else {
final Integer newDigit = getAllowedDigitGreaterThanOrEqualTo(digit + 1);
if (newDigit == null) {
maxResult = null;
} else {
maxResult = newDigit * powerOfTen + minResult;
}
}
powerOfTen *= 10;
}
if (maxResult == null) {
return getAllowedDigitGreaterThanOrEqualTo(1) * powerOfTen + minResult;
} else {
return maxResult;
}
}

Ruby array conversion with even indices [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
With below array:
[68, 205, 286, 347, 482]
I want to generate something like:
[0, 68, 68, 205, 205, 286, 286, 347, 347, 482]
What is the best way to accomplish this in Ruby?
If I am guessing right you want to iterate the array with two neighboring elements at a time. There's each_cons for that:
a = [68, 205, 286, 347, 482]
a.each_cons(2) do |x, y|
p [x, y]
end
# [68, 205]
# [205, 286]
# [286, 347]
# [347, 482]
Are you in fact looking to work through an Array of paired values, to work with ranges of values implied by "joining the dots" of the array? This is not how you have phrased the question, but is an implied property of your output:
([0]+a).each_cons(2).to_a
=> [[0, 68], [68, 205], [205, 286], [286, 347], [347, 482]]
You would then work through the start and end points like this:
([0]+a).each_cons(2) do |x,y|
# x is 0, y is 68 for first iteration
# So you could have (x...y) as a Range for example
end
Or if you really do have your example output as the desired end result, just flatten it:
([0]+a).each_cons(2).to_a.flatten
=> [0, 68, 68, 205, 205, 286, 286, 347, 347, 482]
As said by other, the logic is not really clear. I would write something like this:
array = [68, 205, 286, 347, 482]
first, *middle, last = [0], *array
p first + middle.flat_map{|x|[x,x]} << last
# => [0, 68, 68, 205, 205, 286, 286, 347, 347, 482]
a = [68, 205, 286, 347, 482]
a = a.zip(a.dup).unshift(0).flatten
a.pop
puts a
# => [0, 68, 68, 205, 205, 286, 286, 347, 347, 482]

Mathematical representation of large numbers?

I am attempting to write a function which takes a large number as input (upwards of 800 digits long) and returns a simple formula of no complex math as a string.
By simple math, I mean just numbers with +,-,*,/,^ and () as needed.
'4^25+2^32' = giveMeMath(1125904201809920); // example
Any language would do. I can refactor it, just looking for some help with the logic.
Bonus. The shorter the output the better. Processing time is important. Also, mathematical accuracy is a must.
Update:
to clarify, all input values will be positive integers (no decimals)
I think the entire problem can be recast to a run-length encoding problem on the binary representation of the long integer.
For example, take the following number:
17976931348623159077293051907890247336179769789423065727343008115773
26758055009631327084773224075360211201138798713933576587897688144166
22492847430639474110969959963482268385702277221395399966640087262359
69162804527670696057843280792693630866652907025992282065272811175389
6392184596904358265409895975218053120L
This looks fairly horrendous. In binary, though:
>>> bin(_)
'0b11111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111100000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
0000000'
Which is about 500 ones, followed by 500 zeroes. This suggests an expression like:
2**1024 - 2**512
Which is how I obtained the large number in the first place.
If there are no significantly long runs in the binary representation of the integer, this won't work well at all. 101010101010101010.... is the worst case.
Here is my attempt in Python:
def give_me_math(n):
if n % 2 == 1:
n = n - 1 # we need to make every odd number even, and add back one later
odd = 1
else:
odd = 0
exps = []
while n > 0:
c = 0
num = 0
while num <= n/2:
c += 1
num = 2**c
exps.append(c)
n = n - num
return (exps, odd)
Results:
>>> give_me_math(100)
([6, 5, 2], 0) #2**6 + 2**5 + 2**2 + 0 = 100
>>> give_me_math(99)
([6, 5, 1], 1) #2**6 + 2**5 + 2**1 + 1 = 99
>>> give_me_math(103)
([6, 5, 2, 1], 1) #2**6 + 2**5 + 2**2 + 2**1 + 1 = 103
I believe the results are accurate, but I am not sure about your other criteria.
Edit:
Result: Calculates in about a second.
>>> give_me_math(10**100 + 3435)
([332, 329, 326, 323, 320, 319, 317, 315, 314, 312, 309, 306, 304, 303, 300, 298, 295, 294, 289, 288, 286, 285, 284, 283, 282, 279, 278, 277, 275, 273, 272, 267, 265, 264, 261, 258, 257, 256, 255, 250, 247, 246, 242, 239, 238, 235, 234, 233, 227, 225, 224, 223, 222, 221, 220, 217, 216, 215, 211, 209, 207, 206, 203, 202, 201, 198, 191, 187, 186, 185, 181, 176, 172, 171, 169, 166, 165, 164, 163, 162, 159, 157, 155, 153, 151, 149, 148, 145, 142, 137, 136, 131, 127, 125, 123, 117, 115, 114, 113, 111, 107, 106, 105, 104, 100, 11, 10, 8, 6, 5, 3, 1], 1)
800 digit works fast too:
>>> give_me_math(10**800 + 3452)
But the output is too long to post here, which is OPs concern of course.
Time complexity here is 0(ln(n)), so it is pretty efficient.
In java, you should take a look at the BigDecimal class in java.math package.
I'd suggest you to have a look at
The GMP library (The GNU Multiple Precision Arithmetic Library) for performing the arithmetics
Take a look at integer factorization. The link redirects to Wikipedia which should give probably a good overview. However to be a bit more scientific:
Integer factorization (PDF) by Daniel Bernstein of the University of Illinois
Integer Factorization Algorithms (PDF) by Connelly Barnes of the Department of Physics, Oregon State University

Resources