tarantool pairs fetch not all tuples - tarantool

box.space.test.index.secondary:select({1,'RU', 2})
---
- - [47, 6, 1, 'RU', 2, 11, 6]
- [44, 3, 1, 'RU', 2, 101, 6]
- [42, 1, 1, 'RU', 2, 189, 6]
- [34, 3, 1, 'RU', 2, 260, 5]
- [49, 8, 1, 'RU', 2, 290, 6]
- [41, 0, 1, 'RU', 2, 303, 6]
- [37, 6, 1, 'RU', 2, 494, 5]
- [35, 4, 1, 'RU', 2, 633, 5]
- [45, 4, 1, 'RU', 2, 694, 6]
- [43, 2, 1, 'RU', 2, 780, 6]
- [46, 5, 1, 'RU', 2, 833, 6]
- [40, 9, 1, 'RU', 2, 870, 5]
- [48, 7, 1, 'RU', 2, 927, 6]
- [50, 9, 1, 'RU', 2, 930, 6]
...
box.space.test.index.secondary
---
- unique: false
parts:
- type: NUM
fieldno: 3
- type: STR
fieldno: 4
- type: NUM
fieldno: 5
- type: NUM
fieldno: 6
id: 2
space_id: 512
name: secondary
type: TREE
...
local r='' for k,tuple in box.space.test.index.secondary:pairs({1, 'RU', 2}) do r=r..', found ('..tuple[1]..')' if (tuple[7]<6) then r = r .. ', delete(' ..tuple[1] .. ')' box.space.test:delete(tuple[1]) end end return r
---
- ', found (47), found (44), found (42), found (34), delete(34), found (41), found(37), delete(37), found (45), found (43), found (46), found (40), delete(40), found(50)'
...
box.space.test.index.secondary:select({1,'RU', 2})
---
- - [47, 6, 1, 'RU', 2, 11, 6]
- [44, 3, 1, 'RU', 2, 101, 6]
- [42, 1, 1, 'RU', 2, 189, 6]
- [49, 8, 1, 'RU', 2, 290, 6]
- [41, 0, 1, 'RU', 2, 303, 6]
- [35, 4, 1, 'RU', 2, 633, 5]
- [45, 4, 1, 'RU', 2, 694, 6]
- [43, 2, 1, 'RU', 2, 780, 6]
- [46, 5, 1, 'RU', 2, 833, 6]
- [48, 7, 1, 'RU', 2, 927, 6]
- [50, 9, 1, 'RU', 2, 930, 6]
...
local r='' for k,tuple in box.space.test.index.secondary:pairs({1, 'RU', 2}) do r=r..', found ('..tuple[1]..')' if (tuple[7]<6) then r = r .. ', delete(' ..tuple[1] .. ')' box.space.test:delete(tuple[1]) end end return r
---
- ', found (47), found (44), found (42), found (49), found (41), found (35), delete(35), found (43), found (46), found (48), found (50)'
...
box.space.test.index.secondary:select({1,'RU', 2})
---
- - [47, 6, 1, 'RU', 2, 11, 6]
- [44, 3, 1, 'RU', 2, 101, 6]
- [42, 1, 1, 'RU', 2, 189, 6]
- [49, 8, 1, 'RU', 2, 290, 6]
- [41, 0, 1, 'RU', 2, 303, 6]
- [45, 4, 1, 'RU', 2, 694, 6]
- [43, 2, 1, 'RU', 2, 780, 6]
- [46, 5, 1, 'RU', 2, 833, 6]
- [48, 7, 1, 'RU', 2, 927, 6]
- [50, 9, 1, 'RU', 2, 930, 6]
...
As I see :pairs don't see 35 tuple in first run, and see it only on second execution. Why?
p.s.: sorry for long explanation...

Related

How to prove this josephus problem variation is a np-complete problem?

I have a problem that is a Josephus problem variation. It is described below:
There are m cards with number from 1 to m,and each of them has a unique number. The cards are dispatched to n person who sit in a circle. Note that m >= n.
Then we choose the person "A" who sits at the position "p" to out of the circle, just like the Josephus problem does. Next step we skip "k" person at the right of p while k is the number of the card toked by the person "A", and we do the same thing until only one person left in the circle.
Question is given n person and m cards, can we choose n cards and allocate them to the n person, to make that whether start at which position(exclude the first position), the person survival at the end is always the first person in the circle.
For example, m = n = 5, the only solution is (4, 1, 5, 3, 2).
I think this problem is a np-complete problem, but I can't prove it. Anybody has a good idea to find a polynomial time solution or prove it's np-hard?
--- example solutions ---
2: [ 1, 2]
2: [ 2, 1]
3: [ 1, 3, 2]
3: [ 3, 1, 2]
4: [ 4, 1, 3, 2]
5: [ 4, 1, 5, 3, 2]
7: [ 5, 7, 3, 1, 6, 4, 2]
9: [ 2, 7, 3, 9, 1, 6, 8, 5, 4]
9: [ 3, 1, 2, 7, 6, 5, 9, 4, 8]
9: [ 3, 5, 1, 8, 9, 6, 7, 4, 2]
9: [ 3, 9, 2, 7, 6, 1, 5, 4, 8]
9: [ 6, 1, 8, 3, 7, 9, 4, 5, 2]
10: [ 3, 5, 6, 10, 1, 9, 8, 7, 4, 2]
10: [ 4, 5, 2, 8, 7, 10, 6, 1, 9, 3]
10: [ 5, 1, 9, 2, 10, 3, 7, 6, 8, 4]
10: [ 6, 3, 1, 10, 9, 8, 7, 4, 5, 2]
10: [ 8, 5, 9, 10, 1, 7, 2, 6, 4, 3]
10: [10, 5, 2, 1, 8, 7, 6, 9, 3, 4]
11: [ 2, 1, 10, 11, 9, 3, 7, 5, 6, 8, 4]
11: [ 3, 7, 11, 10, 9, 8, 1, 6, 5, 4, 2]
11: [ 3, 11, 10, 9, 8, 1, 7, 2, 4, 5, 6]
11: [ 4, 1, 10, 2, 9, 8, 7, 5, 11, 3, 6]
11: [ 4, 2, 7, 11, 5, 1, 10, 9, 6, 3, 8]
11: [ 4, 7, 2, 3, 1, 10, 9, 6, 11, 5, 8]
11: [ 4, 7, 3, 9, 11, 10, 1, 8, 6, 5, 2]
11: [ 4, 11, 7, 2, 1, 10, 9, 6, 5, 3, 8]
11: [ 5, 11, 3, 9, 8, 7, 6, 1, 10, 4, 2]
11: [ 6, 1, 10, 2, 9, 8, 7, 5, 11, 3, 4]
11: [ 6, 2, 7, 11, 5, 1, 10, 9, 4, 3, 8]
11: [ 6, 11, 1, 3, 10, 2, 7, 5, 4, 9, 8]
11: [ 9, 5, 3, 1, 10, 2, 8, 7, 11, 6, 4]
12: [ 1, 7, 11, 10, 4, 9, 2, 12, 6, 5, 8, 3]
12: [ 3, 7, 12, 2, 11, 10, 9, 1, 6, 5, 4, 8]
12: [ 3, 8, 11, 2, 12, 9, 1, 7, 5, 10, 4, 6]
12: [ 4, 2, 5, 1, 11, 10, 9, 8, 12, 7, 3, 6]
12: [ 4, 3, 7, 6, 1, 11, 10, 9, 8, 12, 5, 2]
12: [ 5, 1, 6, 11, 9, 2, 10, 7, 12, 8, 3, 4]
12: [ 5, 2, 3, 12, 9, 10, 7, 6, 1, 11, 4, 8]
12: [ 5, 7, 12, 2, 10, 9, 8, 11, 1, 4, 6, 3]
12: [ 7, 1, 2, 3, 5, 9, 10, 8, 11, 6, 12, 4]
12: [ 8, 7, 1, 11, 9, 3, 5, 10, 6, 4, 12, 2]
12: [ 8, 7, 11, 10, 12, 3, 1, 9, 6, 5, 4, 2]
12: [12, 3, 11, 5, 1, 10, 8, 7, 6, 4, 9, 2]
12: [12, 7, 11, 1, 9, 3, 2, 10, 6, 5, 4, 8]
13: [ 2, 1, 4, 7, 11, 6, 3, 10, 13, 5, 8, 12, 9]
13: [ 2, 5, 13, 12, 4, 11, 3, 1, 9, 7, 8, 6, 10]
13: [ 2, 13, 12, 11, 3, 1, 9, 4, 8, 7, 10, 5, 6]
13: [ 3, 5, 2, 1, 12, 9, 11, 10, 7, 6, 13, 4, 8]
13: [ 3, 5, 13, 1, 11, 2, 9, 8, 7, 12, 6, 4, 10]
13: [ 4, 13, 3, 1, 12, 11, 10, 9, 7, 2, 5, 6, 8]
13: [ 6, 4, 3, 1, 10, 11, 13, 5, 9, 12, 7, 8, 2]
13: [ 6, 4, 13, 7, 5, 1, 12, 11, 10, 9, 8, 3, 2]
13: [ 6, 7, 3, 13, 12, 11, 10, 2, 1, 9, 5, 4, 8]
13: [ 6, 7, 13, 11, 2, 10, 9, 1, 8, 12, 5, 3, 4]
13: [ 6, 11, 7, 13, 1, 10, 2, 12, 9, 8, 5, 4, 3]
13: [ 7, 3, 2, 1, 11, 10, 9, 8, 13, 5, 12, 4, 6]
13: [ 7, 5, 13, 3, 10, 11, 2, 9, 1, 6, 8, 4, 12]
13: [ 7, 5, 13, 3, 11, 2, 9, 8, 1, 6, 12, 4, 10]
13: [ 7, 5, 13, 3, 11, 12, 2, 1, 9, 8, 6, 4, 10]
13: [ 7, 9, 1, 11, 3, 13, 2, 10, 12, 6, 5, 4, 8]
13: [ 8, 3, 5, 11, 13, 9, 10, 7, 1, 6, 4, 12, 2]
13: [ 8, 3, 13, 1, 5, 11, 10, 9, 12, 7, 6, 4, 2]
13: [ 9, 3, 13, 2, 10, 4, 1, 7, 6, 5, 12, 11, 8]
13: [ 9, 4, 7, 5, 1, 11, 13, 10, 12, 8, 6, 3, 2]
13: [ 9, 5, 4, 13, 2, 11, 8, 10, 1, 7, 12, 3, 6]
13: [ 9, 5, 13, 4, 11, 1, 8, 3, 7, 12, 6, 10, 2]
13: [10, 4, 3, 5, 13, 1, 9, 11, 7, 6, 8, 12, 2]
13: [11, 2, 7, 3, 12, 1, 10, 9, 6, 5, 13, 4, 8]
13: [11, 13, 5, 2, 10, 9, 8, 7, 1, 6, 4, 3, 12]
13: [11, 13, 7, 1, 12, 9, 2, 3, 10, 5, 4, 6, 8]
13: [12, 1, 3, 5, 11, 13, 4, 10, 9, 8, 7, 6, 2]
13: [12, 7, 13, 3, 11, 1, 9, 8, 6, 5, 10, 4, 2]
13: [12, 13, 7, 11, 2, 5, 1, 9, 10, 6, 4, 3, 8]
13: [13, 3, 1, 12, 11, 2, 9, 10, 7, 6, 4, 5, 8]
13: [13, 3, 7, 1, 5, 12, 4, 10, 9, 8, 11, 6, 2]
14: [ 3, 5, 13, 14, 1, 12, 11, 10, 9, 8, 7, 6, 4, 2]
14: [ 3, 9, 1, 13, 11, 10, 2, 4, 7, 14, 6, 8, 5, 12]
14: [ 3, 14, 4, 12, 11, 1, 9, 8, 2, 13, 7, 5, 10, 6]
14: [ 4, 11, 1, 13, 7, 10, 12, 2, 14, 9, 8, 5, 6, 3]
14: [ 4, 14, 2, 5, 13, 1, 12, 11, 7, 6, 10, 9, 3, 8]
14: [ 5, 7, 1, 13, 12, 11, 10, 2, 9, 8, 14, 6, 4, 3]
14: [ 6, 3, 14, 5, 11, 13, 2, 12, 9, 1, 7, 4, 8, 10]
14: [ 6, 14, 1, 12, 5, 13, 2, 11, 9, 7, 8, 4, 3, 10]
14: [ 7, 5, 13, 12, 1, 11, 4, 10, 2, 14, 9, 8, 6, 3]
14: [ 7, 11, 5, 13, 1, 3, 2, 4, 10, 9, 14, 6, 8, 12]
14: [ 7, 14, 1, 13, 2, 5, 11, 12, 10, 9, 8, 4, 3, 6]
14: [ 8, 7, 5, 13, 2, 11, 3, 9, 10, 12, 1, 14, 4, 6]
14: [11, 2, 10, 5, 8, 7, 9, 1, 13, 14, 12, 4, 3, 6]
14: [11, 3, 14, 2, 13, 1, 10, 8, 9, 7, 5, 12, 4, 6]
14: [11, 5, 3, 14, 2, 1, 13, 10, 8, 7, 6, 12, 4, 9]
14: [11, 14, 5, 3, 13, 1, 10, 2, 9, 4, 7, 8, 12, 6]
14: [12, 1, 14, 3, 13, 4, 10, 9, 2, 7, 6, 5, 11, 8]
14: [12, 11, 7, 5, 13, 3, 2, 14, 1, 9, 8, 4, 6, 10]
14: [12, 14, 7, 13, 6, 5, 11, 1, 10, 9, 8, 4, 3, 2]
14: [13, 1, 7, 2, 11, 3, 9, 14, 8, 6, 5, 10, 4, 12]
14: [13, 11, 3, 1, 4, 2, 7, 10, 9, 6, 14, 12, 5, 8]
14: [14, 1, 13, 3, 11, 5, 10, 9, 2, 6, 8, 7, 4, 12]
14: [14, 5, 1, 13, 12, 2, 11, 3, 7, 9, 6, 8, 4, 10]
--- possibly helpful for a mathematical solution ---
I noticed that starting with length 9, at least one solution for every length has a longish sequence of integers that decrement by 1.
9: [3, 1, 2, 7, 6, 5, 9, 4, 8]
10: [6, 3, 1, 10, 9, 8, 7, 4, 5, 2]
11: [3, 7, 11, 10, 9, 8, 1, 6, 5, 4, 2]
11: [3, 11, 10, 9, 8, 1, 7, 2, 4, 5, 6]
11: [5, 11, 3, 9, 8, 7, 6, 1, 10, 4, 2]
12: [4, 2, 5, 1, 11, 10, 9, 8, 12, 7, 3, 6]
12: [4, 3, 7, 6, 1, 11, 10, 9, 8, 12, 5, 2]
13: [6, 4, 13, 7, 5, 1, 12, 11, 10, 9, 8, 3, 2]
14: [3, 5, 13, 14, 1, 12, 11, 10, 9, 8, 7, 6, 4, 2]
I noticed that for every length I tested except the very small, at least one solution contains a relatively long run of descending
numbers. So far this answer only considers m = n. Here are a few examples; note that excess is n - run_len:
n = 3, run_len = 2, excess = 1: [1] + [3-2] + []
n = 4, run_len = 2, excess = 2: [4, 1] + [3-2] + []
n = 5, run_len = 2, excess = 3: [4, 1, 5] + [3-2] + []
n = 6, no solution
n = 7, run_len = 1, excess = 6: [5] + [7-7] + [3, 1, 6, 4, 2]
n = 8, no solution
n = 9, run_len = 3, excess = 6: [3, 1, 2] + [7-5] + [9, 4, 8]
n = 10, run_len = 4, excess = 6: [6, 3, 1] + [10-7] + [4, 5, 2]
n = 11, run_len = 4, excess = 7: [3, 7] + [11-8] + [1, 6, 5, 4, 2]
n = 12, run_len = 4, excess = 8: [4, 2, 5, 1] + [11-8] + [12, 7, 3, 6]
n = 13, run_len = 5, excess = 8: [6, 4, 13, 7, 5, 1] + [12-8] + [3, 2]
n = 14, run_len = 7, excess = 7: [3, 5, 13, 14, 1] + [12-6] + [4, 2]
n = 15, run_len = 8, excess = 7: [3, 15, 2] + [13-6] + [1, 5, 4, 14]
n = 16, run_len = 6, excess = 10: [6, 3, 1, 10] + [16-11] + [2, 9, 7, 4, 5, 8]
n = 17, run_len = 8, excess = 9: [2, 5, 17, 15, 14, 1] + [13-6] + [4, 3, 16]
n = 18, run_len = 10, excess = 8: [6, 3, 17, 18, 1] + [16-7] + [5, 4, 2]
n = 19, run_len = 10, excess = 9: [4, 19, 3, 17, 18, 1] + [16-7] + [5, 6, 2]
n = 20, no solution found with run_length >= 10
n = 21, run_len = 14, excess = 7: [3, 21, 2] + [19-6] + [1, 5, 4, 20]
n = 22, run_len = 14, excess = 8: [22, 3, 2, 1] + [20-7] + [5, 21, 4, 6]
n = 23, run_len = 14, excess = 9: [7, 1, 23, 3] + [21-8] + [6, 5, 22, 4, 2]
n = 24, run_len = 16, excess = 8: [6, 5, 24, 2] + [22-7] + [3, 1, 23, 4]
n = 25, run_len = 17, excess = 8: [25, 3, 2, 1] + [23-7] + [5, 24, 4, 6]
n = 26, run_len = 17, excess = 9: [26, 3, 25, 2, 1] + [23-7] + [5, 24, 4, 6]
n = 27, run_len = 20, excess = 7: [3, 27, 2] + [25-6] + [1, 5, 4, 26]
n = 28, run_len = 18, excess = 10: [28, 1, 27, 2, 3] + [25-8] + [6, 5, 7, 4, 26]
n = 29, run_len = 20, excess = 9: [2, 5, 29, 27, 26, 1] + [25-6] + [4, 3, 28]
n = 30, run_len = 23, excess = 7: [30, 5, 2, 1] + [28-6] + [29, 3, 4]
n = 31, run_len = 24, excess = 7: [5, 31, 3] + [29-6] + [1, 30, 4, 2]
n = 32, run_len = 23, excess = 9: [7, 32, 31, 2, 1] + [30-8] + [5, 4, 3, 6]
n = 33, run_len = 26, excess = 7: [3, 33, 2] + [31-6] + [1, 5, 4, 32]
n = 34, run_len = 27, excess = 7: [3, 5, 33, 34, 1] + [32-6] + [4, 2]
n = 35, run_len = 27, excess = 8: [5, 35, 3, 33, 34, 1] + [32-6] + [4, 2]
n = 36, run_len = 26, excess = 10: [35, 7, 3, 1, 36, 2] + [34-9] + [6, 5, 4, 8]
n = 37, run_len = 29, excess = 8: [6, 5, 2, 1] + [35-7] + [36, 37, 3, 4]
n = 38, run_len = 29, excess = 9: [3, 7, 37, 38, 1] + [36-8] + [6, 4, 5, 2]
n = 39, run_len = 32, excess = 7: [3, 39, 2] + [37-6] + [1, 5, 4, 38]
n = 40, run_len = 31, excess = 9: [5, 2, 1] + [38-8] + [3, 7, 40, 4, 6, 39]
n = 41, run_len = 33, excess = 8: [3, 5, 1, 40, 2] + [38-6] + [41, 39, 4]
n = 42, run_len = 33, excess = 9: [42, 3, 41, 2, 1] + [39-7] + [5, 4, 40, 6]
n = 43, run_len = 34, excess = 9: [6, 5, 7, 43, 1] + [41-8] + [42, 4, 3, 2]
n = 44, run_len = 35, excess = 9: [5, 3, 2, 1] + [42-8] + [43, 7, 4, 44, 6]
n = 45, run_len = 38, excess = 7: [3, 45, 2] + [43-6] + [1, 5, 4, 44]
n = 50, run_len = 43, excess = 7: [50, 5, 2, 1] + [48-6] + [49, 3, 4]
n = 100, run_len = 91, excess = 9: [5, 2, 1] + [98-8] + [3, 7, 100, 4, 6, 99]
n = 201, run_len = 194, excess = 7: [3, 201, 2] + [199-6] + [1, 5, 4, 200]
20 is missing from the above table because the run length is at most 10, and is taking a long time to compute. No larger value that I've tested has such a small max run length relative to n.
I found these by checking run lengths from n-1 descending, with all possible starting values and permutations of the run & surrounding elements. This reduces the search space immensely.
For a given n, if the max run in any solution to n is length n-k, then this will find it in O(k! * n). While this looks grim, if k has a constant upper bound (e.g. k <= some threshold for all sufficiently large n) then this is effectively O(n). 'Excess' is what I'm calling k in the examples above. I haven't found any greater than 10, but I don't have a solution yet to n = 20. If it has a solution then its excess will exceed 10.
UPDATE: There are a lot of patterns here.
If n mod 6 is 3 and n >= 9, then [3, n, 2, [n-2, n-3, ..., 6], 1, 5, 4, n-1] is valid.
If n mod 12 is 5 and n >= 17 then [2, 5, n, n-2, n-3, 1, [n-4, n-5, ..., 6], 4, 3, n-1] is valid.
If n mod 20 is 10, then [n, 5, 2, 1, [n-2, n-3, ..., 6], n-1, 3, 4] is valid.
If n mod 60 is 7, 11, 31, or 47, then [5, n, 3, [n-2, n-3, ..., 6], 1, n-1, 4, 2] is valid.
If n mod 60 is 6 or 18 and n >= 18 then [6, 3, n-1, n, 1, [n-2, n-3, ..., 7], 5, 4, 2] is valid.
If n mod 60 is 1, 22, 25 or 52 and n >= 22 then [n, 3, 2, 1], [n-2, n-3, ..., 7], 5, n-1, 4, 6] is valid.
If n mod 60 is 23 then [7, 1, n, 3, [n-2, n-3, ..., 8], 6, 5, n-1, 4, 2] is valid.
If n mod 60 is 14 or 34 then [3, 5, n-1, n, 1, [n-2, n-3, ..., 6], 4, 2] is valid.
If n mod 60 is 24 then [6, 5, n, 2, [n-2, n-1, ..., 7], 3, 1, n-1, 4] is valid
If n mod 60 is 2, 6, 26, 42 and n >= 26 then [n, 3, n-1, 2, 1, [n-3, n-4, ..., 7], 5, n-2, 4, 6] is valid.
If n mod 60 is 16 or 28 then [n, 1, n-1, 2, 3, [n-3, n-4, ..., 8], 6, 5, 7, 4, n-2] is valid.
If n mod 60 is 32 then [7, n, n-1, 2, 1, [n-2, n-3, ..., 8], 5, 4, 3, 6] is valid.
If n mod 60 is 35 or 47 then [5, n, 3, n-2, n-1, 1, [n-3, n-4, ..., 6], 4, 2] is valid.
If n mod 60 is 37 then [6, 5, 2, 1, [n-2, n-1, ..., 7], n-1, n, 3, 4]
If n mod 60 is 38 then [3, 7, n-1, n, 1] + [n-2, n-3, ..., 8] + [6, 4, 5, 2]
If n mod 60 is 40 then [5, 2, 1, [n-2, n-3, ..., 8], 3, 7, n, 4, 6, n-1] is valid
If n mod 60 is 0 and n >= 60 then [3, 5, n, 2, [n-2, n-3, ..., 7], 1, 6, n-1, 4] is valid
If n mod 60 is 7, 19, or 31 and n >= 19 then [4, n, 3, n-2, n-1, 1, [n-3, n-4, ..., 7], 5, 6, 2] is valid
If n mod 60 is 23, 38, or 43 then [7, 3, n, 1, [n-2, n-3, ..., 8], 6, 5, n-1, 4, 2] is a valid solution
If n mod 60 is 14 or 44 and n >= 74 then [3, 5, n-1, n, 1, [n-3, n-4, ..., 6], n-2, 4, 2] is valid.
If n mod 60 is 1 or 49 and n >= 49 then [3, 5, n, 1, [n-2, n-3, ..., 7], 2, n-1, 4, 6] is valid.
If n mod 60 is 6, 18, 30, 42, or 54 and n >= 18 then [n, 3, n-1, 2, 1, [n-3, n-4, ..., 7], 5, 4, n-2, 6] is valid.
If n mod 60 is 10, 18, 38 or 58 and n >= 18 then [n-1, 7, 5, n, 1, [n-2, n-3, ..., 8], 2, 6, 4, 3] is valid.
Currently solved for n mod 60 is any of the following values:
0, 1, 2, 3, 5, 6, 7, 9,
10, 11, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 37, 38, 39,
40, 41, 42, 43, 44, 45, 47, 49,
50, 51, 52, 53, 54, 57, 58
Also,
If n mod 42 is 31 then [n, 3, 2, 1, [n-2, n-3, ..., 8], n-1, 5, 4, 7, 6] is valid.
If n mod 420 is 36 or 396 then [n-1, 7, 3, 1, n, 2, [n-2, n-3, ..., 9], 6, 5, 4, 8] is valid.
--- Example for n=21, using the first pattern listed above, and all starting indices.
1: [21, 2, 18, 19, 16, 17, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 5, 4, 20, 1]
2: [ 2, 18, 21, 16, 19, 14, 17, 12, 15, 10, 13, 8, 11, 6, 9, 5, 1, 4, 20, 7]
3: [19, 21, 18, 2, 16, 17, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 5, 4, 20, 1]
4: [18, 21, 19, 17, 2, 15, 16, 13, 14, 11, 12, 9, 10, 7, 8, 1, 5, 4, 20, 6]
5: [17, 21, 19, 18, 16, 2, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 5, 4, 20, 1]
6: [16, 21, 19, 18, 17, 15, 2, 13, 14, 11, 12, 9, 10, 7, 8, 1, 5, 4, 20, 6]
7: [15, 21, 19, 18, 17, 16, 14, 2, 12, 13, 10, 11, 8, 9, 6, 7, 5, 4, 20, 1]
8: [14, 21, 19, 18, 17, 16, 15, 13, 2, 11, 12, 9, 10, 7, 8, 1, 5, 4, 20, 6]
9: [13, 21, 19, 18, 17, 16, 15, 14, 12, 2, 10, 11, 8, 9, 6, 7, 5, 4, 20, 1]
10: [12, 21, 19, 18, 17, 16, 15, 14, 13, 11, 2, 9, 10, 7, 8, 1, 5, 4, 20, 6]
11: [11, 21, 19, 18, 17, 16, 15, 14, 13, 12, 10, 2, 8, 9, 6, 7, 5, 4, 20, 1]
12: [10, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 9, 2, 7, 8, 1, 5, 4, 20, 6]
13: [ 9, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 8, 2, 6, 7, 5, 4, 20, 1]
14: [ 8, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 7, 2, 1, 5, 4, 20, 6]
15: [ 7, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 2, 5, 4, 20, 1]
16: [ 6, 21, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 1, 5, 4, 20, 2]
17: [ 1, 5, 2, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 19, 20, 21]
18: [ 5, 2, 18, 19, 16, 17, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 1, 20, 21]
19: [ 4, 2, 18, 19, 16, 17, 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 5, 20, 21, 1]
20: [20, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 1, 5, 21, 2]
You can observe the same relationship between elements from the decrementing run and other elements for all values of n that the pattern applies to. This isn't a proof, but you can turn this into a proof, though I think the work would need to be done for each pattern separately and it's beyond the scope of what I'm going to spend time on for an S/O question.
--- We can fill in the blanks by using m > n. ---
The pattern [n-1, n, 1, [n-2, n-3, ..., 3], n+5] is valid for n mod 4 is 1 and n >= 9.
The pattern [n, 2, 1, [n-2, n-3, ..., 3], n+4] is valid for n mod 2 is 0 and n >= 6.
With these two, plus what we already found, we get nearly everything. I found these by checking a single replacement value in a limited range.
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 56, 57, 58
If n mod 30 is 29, then [3, n, 2, [n-2, n-3, ..., 4], n-1, n+15) is valid, giving us n mod 60 is 59. We're left with just one unknown: n mod 60 is 55.
...And finally! If n mod 12 is 7 (i.e. n mod 60 is 7, 19, 31, 43, or 55) then [n-1, n, 1, [n-2, n-3, ..., 6], 2, 5, 3, n+4] is valid for all n >= 19.
We now have solutions for all n mod 60, using m=n in most cases, and m=n+15 in the worst case.

How to divide a list of negative and positive numbers into the largest number of subsets whose sum is 0?

I am trying to solve this problem but I can't manage to figure out how.
Let's suppose I have a list of positive and negative numbers whose sum is guaranteed to be 0.
[-10, 1, 2, 20, 5, -100, -80, 10, 15, 15, 60, 100, -20, -18]
I want to obtain a list with the largest number of sub-sets, using all the elements of the initial list only once. And each subset must have the sum 0.
So in the case of this simple input:
[-5, -4, 5, 2, 3, -1]
The best results that can be obtained are:
1. [[-5, 5], [[-4, -1, 2, 3]]] #2 subsets
2. [[-5, 2, 3], [-4, -1, 5]] #2 subsets
These, for example, would be totally wrong answers:
1. [[-5, -4, -1, 2, 3, 5]] #1 subsets that is the initial list, NO
2. [[-5,5]] #1 subset, and not all elements are used, NO
Even if it's NP-Complete, how can I manage to solve it even with a brute-force approach? I just need a solution for small list of numbers.
def get_subsets(lst):
N = len(lst)
cand = []
dp = [0 for x in range(1<<N)] # maximum number of subsets using elements represented by bitset
back = [0 for x in range(1<<N)]
# Section 1
for i in range(1,1<<N):
cur = 0
for j in range(N):
if i&(1<<j):
cur += lst[j]
if not cur:
cand.append(i) # if subset sums to 0, it's viable
dp[0] = 1
# Section 2
for i in range(1<<N):
while cand and cand[0] <= i:
cand.pop(0)
if not dp[i]:
continue
for j in cand:
if i&j: # if subsets intersect, it cannot be added
continue
if dp[i]+1 > dp[i|j]:
back[i|j] = j
dp[i|j] = dp[i]+1
# Section 3
ind = dp.index(max(dp))
res = []
while back[ind]:
cur = []
for i in range(N):
if back[ind]&(1<<i):
cur.append(lst[i])
res.append(cur)
ind = ind^back[ind]
return res
print (get_subsets([-5, -4, 5, 2, 3, -1]))
Basically, this solution collects all subsets of the original list that can sum to zero, then attempts to merge as many of them together as possible without colliding. It runs in worst-case O(2^{2N}) time, where N is the length of the list, but it should hit an average case of around O(2^N), since there typically shouldn't be too many subsets summing to 0.
EDIT: I added sections to facilitate explanation of the algorithm
Section 1: I iterate through all possible 2^N-1 nonempty subsets of the original list, and check which of these subsets sum to 0; any viable zero-sum subsets are added to the list cand (represented as an integer in the range [1,2^N-1] with bits set at the indices making up the subset).
Section 2: dp is a dynamic programming table storing the maximum number of subsets summing to 0 that can be formed using the subset represented by the integer i at dp[i]. Initially, all entries of dp are set to 0 except dp[0] = 1, since the empty set has a sum of 0. Then I iterate through each subset from 0 to 2^N-1, and I run through the list of candidate subsets and attempt to merge the two subsets.
Section 3: This is just backtracking to find the answer: while filling in dp, I also kept an array back that stores the most recent subset added to achieve the subset i at back[i]. So I find the subset that maximizes the number of sub-subsets summing to 0 with ind = dp.index(max(dp)), and then I backtrack from there, shrinking the subset by removing the most recently added subset until I finally arrive back to the empty set.
This problem is NP-complete, since it is a combination of two NP-complete problems:
finding a single subset whose sum is 0 is known as the subset sum problem
when you find all the subsets whose sum is 0, you have to solve an exact cover problem with a special condition: you want to maximize the number of subsets.
The following steps will provide a solution:
use dynamic programming to find the subsets whose sum is 0 ('https://en.wikipedia.org/wiki/Subset_sum_problem#Pseudo-polynomial_time_dynamic_programming_solution)
to maximize the number of subsets, one would use D. Knuth's Algorithm X to find the exact cover.
A few remarks:
First, we know that there is an exact cover because the list of numbers has a sum of 0.
Second, we can use only the subsets that are not supersets of any other subset. Because, if A is a superset of X (both sum to 0), A can't be in the cover that has the largest number of subsets. Let A, B, C, ... be the cover with the maximum number of subsets, then we can replace A by X and A\X (it is trivial to see that the sum of A\X elements is 0) and we get the cover X, A\X, B, C, ... that is better.
Third, when we use Algorithm X, all paths in the search tree will lead to a success. Let A, B, C, ... be a path composed of non overlapping subsets having each a sum of 0. Then the complent has also a sum of 0 (which may be a superset of another subset, and then we'll use 2.).
As you see, nothing new here, and I will use only well known techniques/algorithms.
Find the subsets having a sum of 0.
The algorithm is well known. Here's a Python implementation based on Wikipedia explanations
class Q:
def __init__(self, values):
self.len = len(values)
self.min = sum(e for e in values if e <= 0)
self.max = sum(e for e in values if e >= 0)
self._arr = [False] * self.len * (self.max - self.min + 1)
def __getitem__(self, item):
index, v = item
return self._arr[v * self.len + index]
def __setitem__(self, item, value):
index, v = item
self._arr[v * self.len + index] = value
class SubsetSum:
def __init__(self, values):
self._values = values
self._q = Q(values)
def prepare(self):
for s in range(self._q.min, self._q.max + 1):
self._q[0, s] = (self._values[0] == s)
for i in range(self._q.len):
self._q[i, 0] = True
for i in range(1, self._q.len):
v = self._values[i]
for s in range(self._q.min, self._q.max + 1):
self._q[i, s] = (v == s) or self._q[i - 1, s] or self._q[
i - 1, s - v]
def subsets(self, target=0):
yield from self._subsets(self._q.len - 1, target, [])
def _subsets(self, i, target, p):
assert i >= 0
v = self._values[i]
c = self._q[i - 1, target]
b = self._q[i - 1, target - v]
if i == 0:
if target == 0:
if p:
yield p
elif self._q[0, target]:
yield p + [i]
else:
if self._q.min <= target - v <= self._q.max and self._q[
i - 1, target - v]:
yield from self._subsets(i - 1, target - v, p + [i])
if self._q[i - 1, target]:
yield from self._subsets(i - 1, target, p)
Here's how it works:
arr = [-10, 1, 2, 20, 5, -100, -80, 10, 15, 15, 60, 100, -20, -18]
arr = sorted(arr)
s = SubsetSum(arr)
s.prepare()
subsets0 = list(s.subsets())
print(subsets0)
Output:
[[13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], [13, 12, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0], [13, 12, 11, 10, 9, 4, 2, 1, 0], [13, 12, 11, 10, 8, 7, 4, 2, 1, 0], [13, 12, 11, 10, 8, 6, 5, 4, 3, 1, 0], [13, 12, 11, 10, 7, 2, 1, 0], [13, 12, 11, 10, 6, 5, 3, 1, 0], [13, 12, 11, 9, 8, 7, 4, 2, 1, 0], [13, 12, 11, 9, 8, 6, 5, 4, 3, 1, 0], [13, 12, 11, 9, 7, 2, 1, 0], [13, 12, 11, 9, 6, 5, 3, 1, 0], [13, 12, 11, 8, 7, 6, 5, 3, 1, 0], [13, 12, 11, 8, 4, 1, 0], [13, 12, 11, 1, 0], [13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 1, 0], [13, 12, 10, 9, 8, 2, 1, 0], [13, 12, 10, 9, 7, 6, 5, 3, 1, 0], [13, 12, 10, 9, 4, 1, 0], [13, 12, 10, 8, 7, 4, 1, 0], [13, 12, 10, 7, 1, 0], [13, 12, 9, 8, 7, 4, 1, 0], [13, 12, 9, 7, 1, 0], [13, 11, 10, 8, 6, 5, 4, 3, 2, 0], [13, 11, 10, 6, 5, 3, 2, 0], [13, 11, 9, 8, 6, 5, 4, 3, 2, 0], [13, 11, 9, 6, 5, 3, 2, 0], [13, 11, 8, 7, 6, 5, 3, 2, 0], [13, 11, 8, 4, 2, 0], [13, 11, 7, 6, 5, 4, 3, 2, 1], [13, 11, 7, 6, 5, 4, 3, 0], [13, 11, 2, 0], [13, 10, 9, 8, 7, 6, 5, 4, 3, 2, 0], [13, 10, 9, 7, 6, 5, 3, 2, 0], [13, 10, 9, 4, 2, 0], [13, 10, 8, 7, 4, 2, 0], [13, 10, 8, 6, 5, 4, 3, 2, 1], [13, 10, 8, 6, 5, 4, 3, 0], [13, 10, 7, 2, 0], [13, 10, 6, 5, 3, 2, 1], [13, 10, 6, 5, 3, 0], [13, 9, 8, 7, 4, 2, 0], [13, 9, 8, 6, 5, 4, 3, 2, 1], [13, 9, 8, 6, 5, 4, 3, 0], [13, 9, 7, 2, 0], [13, 9, 6, 5, 3, 2, 1], [13, 9, 6, 5, 3, 0], [13, 8, 7, 6, 5, 3, 2, 1], [13, 8, 7, 6, 5, 3, 0], [13, 8, 4, 2, 1], [13, 8, 4, 0], [13, 7, 6, 5, 4, 3, 1], [13, 2, 1], [13, 0], [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 0], [12, 11, 10, 9, 8, 2, 0], [12, 11, 10, 9, 7, 6, 5, 3, 2, 1], [12, 11, 10, 9, 7, 6, 5, 3, 0], [12, 11, 10, 9, 4, 2, 1], [12, 11, 10, 9, 4, 0], [12, 11, 10, 8, 7, 4, 2, 1], [12, 11, 10, 8, 7, 4, 0], [12, 11, 10, 8, 6, 5, 4, 3, 1], [12, 11, 10, 7, 2, 1], [12, 11, 10, 7, 0], [12, 11, 10, 6, 5, 3, 1], [12, 11, 9, 8, 7, 4, 2, 1], [12, 11, 9, 8, 7, 4, 0], [12, 11, 9, 8, 6, 5, 4, 3, 1], [12, 11, 9, 7, 2, 1], [12, 11, 9, 7, 0], [12, 11, 9, 6, 5, 3, 1], [12, 11, 8, 7, 6, 5, 3, 1], [12, 11, 8, 4, 1], [12, 11, 1], [12, 10, 9, 8, 7, 6, 5, 4, 3, 1], [12, 10, 9, 8, 2, 1], [12, 10, 9, 8, 0], [12, 10, 9, 7, 6, 5, 3, 1], [12, 10, 9, 4, 1], [12, 10, 8, 7, 4, 1], [12, 10, 7, 1], [12, 9, 8, 7, 4, 1], [12, 9, 7, 1], [11, 10, 8, 6, 5, 4, 3, 2], [11, 10, 6, 5, 3, 2], [11, 9, 8, 6, 5, 4, 3, 2], [11, 9, 6, 5, 3, 2], [11, 8, 7, 6, 5, 3, 2], [11, 8, 4, 2], [11, 7, 6, 5, 4, 3], [11, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2], [10, 9, 7, 6, 5, 3, 2], [10, 9, 4, 2], [10, 8, 7, 4, 2], [10, 8, 6, 5, 4, 3], [10, 7, 2], [10, 6, 5, 3], [9, 8, 7, 4, 2], [9, 8, 6, 5, 4, 3], [9, 7, 2], [9, 6, 5, 3], [8, 7, 6, 5, 3], [8, 4]]
Reduce the number of subsets
We have 105 subsets that sum to 0, but we can remove the subsets that are superset of other subsets. We need a function to find if a list of elements contains all elements in another list. In Python:
import collections
def contains(l1, l2):
"""
Does l1 contain all elements of l2?
"""
c = collections.Counter(l1)
for e in l2:
c[e] -= 1
return all(n >= 0 for n in c.values())
Now, we can remove the subsets that are supersets of another subset.
def remove_supersets(subsets):
subsets = sorted(subsets, key=len)
new_subsets = []
for i, s1 in enumerate(subsets):
for s2 in subsets[:i]: # smaller subsets
if contains(s1, s2):
break
else: # not a superset
new_subsets.append(s1)
return new_subsets
In our situation:
subsets0 = remove_supersets(subsets0)
print(len(subsets0))
Output:
[[13, 0], [11, 2], [8, 4], [13, 2, 1], [12, 11, 1], [10, 7, 2], [9, 7, 2], [12, 10, 7, 1], [12, 9, 7, 1], [10, 9, 4, 2], [10, 6, 5, 3], [9, 6, 5, 3], [12, 11, 10, 7, 0], [12, 11, 9, 7, 0], [12, 10, 9, 8, 0], [12, 10, 9, 4, 1], [8, 7, 6, 5, 3], [12, 11, 10, 9, 4, 0], [12, 10, 9, 8, 2, 1], [11, 7, 6, 5, 4, 3], [13, 7, 6, 5, 4, 3, 1]]
[[0, 2, 10, 6, 4], [0, 2, 10, 8, 1], [0, 2, 11, 5, 4], [0, 2, 11, 7, 1], [0, 16, 9, 4], [0, 16, 15, 1], [0, 18, 19], [3, 2, 12, 11], [3, 2, 13, 10], [3, 17, 16], [3, 19, 14], [20, 14, 1]]
We managed to reduce the number of subsets to 21, that is a good improvement since we need to explore all possibilities to find an exact cover.
Algorithm X
I do not use the dancing links here (I think that technique is we'll designed for low level languages like C, but you can implement them in Python if you want). We just need to keep track of the remaing subsets:
class Matrix:
def __init__(self, subsets, ignore_indices=set()):
self._subsets = subsets
self._ignore_indices = ignore_indices
def subset_values(self, i):
assert i not in self._ignore_indices
return self._subsets[i]
def value_subsets_indices(self, j):
return [i for i, s in self._subsets_generator() if j in s]
def _subsets_generator(self):
return ((i, s) for i, s in enumerate(self._subsets) if
i not in self._ignore_indices)
def rarest_value(self):
c = collections.Counter(
j for _, s in self._subsets_generator() for j in s)
return c.most_common()[-1][0]
def take_subset(self, i):
s = self._subsets[i]
to_ignore = {i2 for i2, s2 in self._subsets_generator() if
set(s2) & set(s)}
return Matrix(self._subsets,
self._ignore_indices | to_ignore)
def __bool__(self):
return bool(list(self._subsets_generator()))
And finally the cover function:
def cover(m, t=[]):
if m: # m is not empty
j = m.rarest_value()
for i in m.value_subsets_indices(j):
m2 = m.take_subset(i)
yield from cover(m2, t + [i])
else:
yield t
Finally, we have:
m = Matrix(subsets0)
ts = list(cover(m))
t = max(ts, key=len)
print([[arr[j] for j in subsets0[i]] for i in t])
Output:
[[100, -100], [10, -10], [15, 2, 1, -18], [15, 5, -20], [60, 20, -80]]
Below essentially the same idea as Michael Huang, with 30 more lines...
A solution with cliques
We can prebuild all subsets whose sum is 0.
Build subsets of 1 elem;
then of size 2 by reusing the previous ones
and keep those whose sum is zero along the way
Now say such subset is a node of a graph.
Then a node is in relation with another one iff their associated subset has no number in common.
We thus want to build the maximum clique of the graph:
In a clique, all nodes are in relation idem their subsets are disjoints
The maximum clique gives us the maximal number of subsets
function forall (v, reduce) {
const nexts = v.map((el, i) => ({ v: [el], i, s: el })).reverse()
while (nexts.length) {
const next = nexts.pop()
for (let i = next.i + 1; i < v.length; ++i) {
const { s, skip } = reduce(next, v[i])
if (!skip) {
nexts.push({ v: next.v.concat(v[i]), s: s, i })
}
}
}
}
function buildSubsets (numbers) {
const sums = []
forall(numbers, (next, el) => {
const s = next.s + el
if (s === 0) {
sums.push({ s, v: next.v.concat(el) })
return { s, skip: true }
}
return { s }
})
return sums
}
const bin2decs = bin => {
const v = []
const s = bin.toString(2)
for (let i = 0; i < s.length; ++i) {
if (intersects(dec2bin(i), bin)) {
v.push(i)
}
}
return v
}
const dec2bin = dec => Math.pow(2, dec)
const decs2bin = decs => decs.reduce((bin, dec) => union(dec2bin(dec), bin), 0)
// Set methods on int
const isIn = (a, b) => (a & b) === a
const intersects = (a, b) => a & b
const union = (a, b) => a | b
// if a subset contains another one, discard it
// e.g [1,2,4] should be discarded if [1,2] is present
const cleanSubsets = bins => bins.filter(big => bins.every(b => big === b || !isIn(b, big)))
function bestClique (decs) {
const cliques = []
forall(decs, (next, el) => {
if (intersects(next.s, el)) { return { skip: true } }
const s = union(next.s, el)
cliques.push({ s, v: next.v.concat(el) })
return { s }
})
return cliques.sort((a, b) => b.v.length - a.v.length)[0]
}
// in case we have duplicated numbers in the list,
// they are still uniq thanks to their id: i (idem position in the list)
const buildNumbers = v => v.map((n, i) => {
const u = new Number(n)
u.i = i
return u
})
function run (v) {
const numbers = buildNumbers(v)
const subs = buildSubsets(numbers)
const bins = subs.map(s => decs2bin(s.v.map(n => n.i)))
const clique = bestClique(cleanSubsets(bins))
const indexedSubs = clique.v.map(bin2decs)
const subsets = indexedSubs.map(sub => sub.map(i => numbers[i].valueOf()))
console.log('subsets', JSON.stringify(subsets))
}
run([1, -1, 2, -2])
run([-10, 1, 2, 20, 5, -100, -80, 10, 15, 15, 60, 100, -20, -18, 10, -10])
run([-5, -4, 5, 2, 3, -1])

Ruby correct code for nested loop for Euler 8

Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
https://projecteuler.net/problem=8
data = '''73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450'''
The code is:
def largest_product_series
mx = 0
arr = data.split("")
arr.map!{ |x| x.to_i}
(arr.size - 13).times do |i|
0.upto(13) do |c|
result = arr.inject() {|sum,c | sum * arr[i + c]}
puts result
if result >= mx
mx = result
end
end
end
#puts "#{mx}"
mx
end
It is actually from Euler project 8 which I am working on. please help me to correct my code and give me some advise, I keep getting a hundred digit output.
A Rubyish way of doing that is as follows.
data = '73167176531330624919225119674426574742355349194934' +
'96983520312774506326239578318016984801869478851843' +
'85861560789112949495459501737958331952853208805511' +
'12540698747158523863050715693290963295227443043557' +
'66896648950445244523161731856403098711121722383113' +
'62229893423380308135336276614282806444486645238749' +
'30358907296290491560440772390713810515859307960866' +
'70172427121883998797908792274921901699720888093776' +
'65727333001053367881220235421809751254540594752243' +
'52584907711670556013604839586446706324415722155397' +
'53697817977846174064955149290862569321978468622482' +
'83972241375657056057490261407972968652414535100474' +
'82166370484403199890008895243450658541227588666881' +
'16427171479924442928230863465674813919123162824586' +
'17866458359124566529476545682848912883142607690042' +
'24219022671055626321111109370544217506941658960408' +
'07198403850962455444362981230987879927244284909188' +
'84580156166097919133875499200524063689912560717606' +
'05886116467109405077541002256983155200055935729725' +
'71636269561882670428252483600823257530420752963450'
def prod(arr)
arr.reduce(1, :*)
end
arr = data.each_char.map(&:to_i).each_cons(13).max_by { |a| prod(a) }
#=> [5, 5, 7, 6, 6, 8, 9, 6, 6, 4, 8, 9, 5]
[arr.join, prod(arr)]
#=> ["5576689664895", 23514624000]
The steps are as follows. Suppose
data = '731671765313326'
(data.size #=> 15). Then
b = data.each_char.map(&:to_i)
#=> [7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 2, 6]
c = b.each_cons(13)
#=> #<Enumerator: [7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 2, 6]:each_cons(13)>
We can see the elements that will be generated by this enumerator by converting it to an array:
c.to_a
#=> [[7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3],
# [3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 2],
# [1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 2, 6]]
arr = c.max_by { |a| prod(a) }
#=> [7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3]
This was obtained by computing:
[prod [7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3],
prod [3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 2],
prod [1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3, 2, 6]].max
#=> [5_000_940, 1_428_840, 2_857_680].max
#=> 5000940
The last step is to return the array
[arr.join, prod(arr)]
#=> [[7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3].join,
#=> prod([7, 3, 1, 6, 7, 1, 7, 6, 5, 3, 1, 3, 3])]
#=> ["7316717653133", 5000940]

Performance analysis of openmp code (parallel) vs serial code

How do I compare the performance of parallel code(using OpenMP) vs serial code? I am using the following method
int arr[1000] = {1, 6, 1, 3, 1, 9, 7, 3, 2, 0, 5, 0, 8, 9, 8, 4, 4, 4, 0, 9, 6, 5, 9, 5, 9, 2, 5, 8, 6, 1, 0, 7, 7, 3, 2, 8, 3, 2, 3, 7, 2, 0, 7, 2, 9, 5, 8, 6, 2, 8, 5, 8, 5, 6, 3, 5, 8, 1, 3, 7, 2, 6, 6, 2, 1, 9, 0, 6, 1, 6, 3, 5, 6, 3, 0, 8, 0, 8, 4, 2, 7, 1, 0, 2, 7, 6, 9, 7, 7, 5, 4, 9, 3, 1, 1, 4, 2, 4, 1, 5, 2, 6, 0, 8, 9, 2, 6, 0, 1, 0, 2, 0, 3, 3, 4, 0, 1, 4, 8, 8, 1, 4, 9, 4, 7, 3, 8, 9, 9, 1, 4, 1, 8, 7, 9, 9, 9, 8, 9, 0, 0, 4, 2, 4, 9, 7, 6, 0, 3, 4, 8, 6, 1, 9, 0, 8, 2, 0, 8, 1, 2, 4, 2, 2, 1, 4, 1, 1, 4, 3, 3, 4, 9, 8, 0, 8, 7, 7, 8, 0, 3, 8, 8, 4, 7, 8, 5, 2, 0, 3, 3, 4, 9, 8, 6, 1, 4, 0, 4, 8, 5, 9, 4, 4, 7, 5, 2, 4, 2, 2, 6, 5, 2, 4, 2, 1, 4, 7, 3, 5, 2, 7, 9, 1, 7, 8, 4, 3, 0, 8, 1, 5, 8, 7, 1, 7, 2, 5, 2, 6, 9, 8, 2, 1, 5, 4, 2, 9, 1, 6, 6, 5, 5, 8, 6, 4, 6, 1, 7, 8, 1, 0, 3, 9, 7, 6, 7, 2, 1, 1, 8, 2, 9, 2, 3, 6, 8, 7, 8, 9, 5, 4, 4, 2, 2, 3, 6, 8, 4, 5, 6, 5, 7, 1, 7, 7, 9, 6, 9, 2, 7, 9, 4, 8, 2, 7, 5, 0, 7, 3, 2, 2, 9, 8, 7, 2, 3, 5, 2, 9, 1, 1, 5, 8, 4, 4, 5, 4, 0, 6, 6, 9, 8, 1, 7, 0, 0, 4, 2, 7, 9, 6, 2, 9, 7, 9, 1, 0, 4, 3, 0, 7, 6, 7, 8, 1, 1, 5, 5, 3, 4, 3, 2, 2, 4, 1, 2, 7, 6, 6, 4, 5, 3, 8, 4, 2, 9, 7, 2, 6, 3, 4, 3, 9, 1, 1, 0, 4, 9, 5, 7, 3, 9, 1, 5, 5, 5, 9, 2, 3, 5, 9, 8, 0, 9, 5, 2, 9, 4, 7, 5, 7, 1, 0, 7, 5, 4, 7, 9, 3, 5, 9, 8, 6, 2, 3, 1, 7, 2, 6, 0, 9, 7, 1, 2, 6, 8, 4, 5, 2, 3, 2, 2, 7, 3, 9, 2, 9, 6, 3, 2, 3, 2, 2, 9, 7, 5, 3, 4, 9, 9, 7, 8, 6, 0, 0, 4, 0, 7, 2, 4, 0, 4, 6, 9, 9, 5, 1, 0, 4, 5, 4, 7, 9, 6, 9, 6, 1, 2, 3, 0, 3, 2, 1, 1, 4, 1, 5, 4, 0, 7, 8, 3, 4, 5, 2, 5, 2, 6, 6, 6, 1, 0, 6, 2, 9, 5, 1, 0, 9, 6, 3, 4, 8, 4, 5, 2, 7, 2, 8, 8, 2, 6, 1, 6, 3, 5, 3, 6, 1, 1, 4, 4, 2, 0, 7, 1, 7, 0, 3, 8, 6, 6, 2, 6, 2, 7, 0, 0, 2, 8, 0, 4, 6, 3, 2, 0, 8, 5, 8, 2, 7, 2, 6, 1, 5, 5, 4, 4, 5, 9, 3, 3, 8, 7, 9, 0, 7, 1, 2, 9, 1, 2, 3, 8, 7, 5, 0, 8, 0, 8, 0, 9, 2, 6, 0, 7, 2, 6, 4, 9, 6, 7, 3, 4, 6, 4, 6, 3, 6, 9, 2, 7, 3, 5, 7, 1, 2, 7, 9, 5, 7, 1, 4, 0, 7, 7, 9, 1, 3, 3, 1, 1, 2, 4, 5, 9, 0, 4, 4, 6, 3, 7, 6, 8, 4, 3, 1, 7, 1, 2, 2, 8, 3, 6, 0, 1, 5, 0, 2, 1, 5, 5, 2, 0, 9, 0, 1, 0, 4, 5, 8, 7, 2, 4, 7, 7, 0, 9, 6, 1, 1, 8, 1, 5, 6, 4, 8, 2, 4, 0, 3, 1, 6, 5, 1, 7, 7, 4, 9, 1, 0, 0, 0, 4, 6, 8, 3, 6, 7, 9, 9, 0, 9, 3, 5, 6, 7, 3, 8, 3, 6, 3, 4, 4, 0, 8, 1, 8, 2, 3, 1, 4, 3, 2, 9, 1, 0, 4, 8, 9, 4, 9, 9, 3, 2, 7, 1, 9, 0, 1, 4, 8, 4, 9, 2, 7, 9, 6, 5, 1, 1, 6, 8, 4, 0, 9, 7, 2, 3, 5, 1, 9, 7, 3, 5, 9, 0, 6, 1, 2, 8, 5, 1, 4, 6, 5, 1, 5, 3, 8, 9, 4, 7, 7, 0, 9, 6, 8, 2, 9, 3, 5, 9, 2, 8, 4, 2, 0, 2, 5, 3, 2, 2, 6, 7, 9, 3, 0, 6, 7, 1, 5, 1, 0, 2, 2, 9, 0, 2, 1, 2, 7, 7, 3, 0, 7, 9, 4, 8, 1, 9, 3, 4, 1, 1, 3, 2, 6, 3, 9, 3, 6, 6, 7, 6, 1, 1, 6, 1, 3, 9, 3, 2, 6, 8, 2, 6, 7, 6, 4, 1, 5, 9, 5, 9, 2, 0, 3, 8, 5, 2, 4, 2, 9, 3, 8, 0, 6, 6, 3, 1, 6, 9, 3, 2, 7, 6, 0, 7, 2, 6, 8, 0, 5, 5, 9, 9, 5, 4, 8, 0, 7, 4, 2, 8, 9, 3, 0, 5, 9, 3, 6, 5, 4, 9, 0, 2, 7, 2, 9, 0, 9, 9, 2, 6, 4, 3, 6, 9, 7, 6, 1, 6, 0, 6, 4, 9, 9, 6, 6, 0, 2, 2, 6, 6, 3, 8, 8, 1, 0, 9, 3, 9, 8, 5, 6, 4, 8, 4, 3, 5, 0, 7, 2, 2, 3, 8, 3, 2, 5, 9, 2, 7, 1, 0, 5, 6, 0, 4};
clock_t begin, end;
double time_spent;
begin = clock();
/* here, do your time-consuming job */
#pragma omp parallel for private(temp)
for(j=0;j<1000;j++){
temp = arr[j];
for(i=0;i<temp;temp--)
result[j]=result[j]*temp;
}
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("\n\n%f",time_spent);
But every time I run the code I get a different output. I want to see how the performance of the code differs for openmp and serial code. What method I should use to achieve the same?
The time the code takes to run will change a little bit due to computer/server usage; however, if you run both the parallel and serial versions you should see a difference in the amount of run time between the two. Also, the size of your parallel operation is pretty small. But you should see and improvement.
int arr[1000] = {1, 6, 1, 3, 1, 9, 7, 3, 2, 0, 5, 0, 8, 9, 8, 4, 4, 4, 0, 9, 6, 5, 9, 5, 9, 2, 5, 8, 6, 1, 0, 7, 7, 3, 2, 8, 3, 2, 3, 7, 2, 0, 7, 2, 9, 5, 8, 6, 2, 8, 5, 8, 5, 6, 3, 5, 8, 1, 3, 7, 2, 6, 6, 2, 1, 9, 0, 6, 1, 6, 3, 5, 6, 3, 0, 8, 0, 8, 4, 2, 7, 1, 0, 2, 7, 6, 9, 7, 7, 5, 4, 9, 3, 1, 1, 4, 2, 4, 1, 5, 2, 6, 0, 8, 9, 2, 6, 0, 1, 0, 2, 0, 3, 3, 4, 0, 1, 4, 8, 8, 1, 4, 9, 4, 7, 3, 8, 9, 9, 1, 4, 1, 8, 7, 9, 9, 9, 8, 9, 0, 0, 4, 2, 4, 9, 7, 6, 0, 3, 4, 8, 6, 1, 9, 0, 8, 2, 0, 8, 1, 2, 4, 2, 2, 1, 4, 1, 1, 4, 3, 3, 4, 9, 8, 0, 8, 7, 7, 8, 0, 3, 8, 8, 4, 7, 8, 5, 2, 0, 3, 3, 4, 9, 8, 6, 1, 4, 0, 4, 8, 5, 9, 4, 4, 7, 5, 2, 4, 2, 2, 6, 5, 2, 4, 2, 1, 4, 7, 3, 5, 2, 7, 9, 1, 7, 8, 4, 3, 0, 8, 1, 5, 8, 7, 1, 7, 2, 5, 2, 6, 9, 8, 2, 1, 5, 4, 2, 9, 1, 6, 6, 5, 5, 8, 6, 4, 6, 1, 7, 8, 1, 0, 3, 9, 7, 6, 7, 2, 1, 1, 8, 2, 9, 2, 3, 6, 8, 7, 8, 9, 5, 4, 4, 2, 2, 3, 6, 8, 4, 5, 6, 5, 7, 1, 7, 7, 9, 6, 9, 2, 7, 9, 4, 8, 2, 7, 5, 0, 7, 3, 2, 2, 9, 8, 7, 2, 3, 5, 2, 9, 1, 1, 5, 8, 4, 4, 5, 4, 0, 6, 6, 9, 8, 1, 7, 0, 0, 4, 2, 7, 9, 6, 2, 9, 7, 9, 1, 0, 4, 3, 0, 7, 6, 7, 8, 1, 1, 5, 5, 3, 4, 3, 2, 2, 4, 1, 2, 7, 6, 6, 4, 5, 3, 8, 4, 2, 9, 7, 2, 6, 3, 4, 3, 9, 1, 1, 0, 4, 9, 5, 7, 3, 9, 1, 5, 5, 5, 9, 2, 3, 5, 9, 8, 0, 9, 5, 2, 9, 4, 7, 5, 7, 1, 0, 7, 5, 4, 7, 9, 3, 5, 9, 8, 6, 2, 3, 1, 7, 2, 6, 0, 9, 7, 1, 2, 6, 8, 4, 5, 2, 3, 2, 2, 7, 3, 9, 2, 9, 6, 3, 2, 3, 2, 2, 9, 7, 5, 3, 4, 9, 9, 7, 8, 6, 0, 0, 4, 0, 7, 2, 4, 0, 4, 6, 9, 9, 5, 1, 0, 4, 5, 4, 7, 9, 6, 9, 6, 1, 2, 3, 0, 3, 2, 1, 1, 4, 1, 5, 4, 0, 7, 8, 3, 4, 5, 2, 5, 2, 6, 6, 6, 1, 0, 6, 2, 9, 5, 1, 0, 9, 6, 3, 4, 8, 4, 5, 2, 7, 2, 8, 8, 2, 6, 1, 6, 3, 5, 3, 6, 1, 1, 4, 4, 2, 0, 7, 1, 7, 0, 3, 8, 6, 6, 2, 6, 2, 7, 0, 0, 2, 8, 0, 4, 6, 3, 2, 0, 8, 5, 8, 2, 7, 2, 6, 1, 5, 5, 4, 4, 5, 9, 3, 3, 8, 7, 9, 0, 7, 1, 2, 9, 1, 2, 3, 8, 7, 5, 0, 8, 0, 8, 0, 9, 2, 6, 0, 7, 2, 6, 4, 9, 6, 7, 3, 4, 6, 4, 6, 3, 6, 9, 2, 7, 3, 5, 7, 1, 2, 7, 9, 5, 7, 1, 4, 0, 7, 7, 9, 1, 3, 3, 1, 1, 2, 4, 5, 9, 0, 4, 4, 6, 3, 7, 6, 8, 4, 3, 1, 7, 1, 2, 2, 8, 3, 6, 0, 1, 5, 0, 2, 1, 5, 5, 2, 0, 9, 0, 1, 0, 4, 5, 8, 7, 2, 4, 7, 7, 0, 9, 6, 1, 1, 8, 1, 5, 6, 4, 8, 2, 4, 0, 3, 1, 6, 5, 1, 7, 7, 4, 9, 1, 0, 0, 0, 4, 6, 8, 3, 6, 7, 9, 9, 0, 9, 3, 5, 6, 7, 3, 8, 3, 6, 3, 4, 4, 0, 8, 1, 8, 2, 3, 1, 4, 3, 2, 9, 1, 0, 4, 8, 9, 4, 9, 9, 3, 2, 7, 1, 9, 0, 1, 4, 8, 4, 9, 2, 7, 9, 6, 5, 1, 1, 6, 8, 4, 0, 9, 7, 2, 3, 5, 1, 9, 7, 3, 5, 9, 0, 6, 1, 2, 8, 5, 1, 4, 6, 5, 1, 5, 3, 8, 9, 4, 7, 7, 0, 9, 6, 8, 2, 9, 3, 5, 9, 2, 8, 4, 2, 0, 2, 5, 3, 2, 2, 6, 7, 9, 3, 0, 6, 7, 1, 5, 1, 0, 2, 2, 9, 0, 2, 1, 2, 7, 7, 3, 0, 7, 9, 4, 8, 1, 9, 3, 4, 1, 1, 3, 2, 6, 3, 9, 3, 6, 6, 7, 6, 1, 1, 6, 1, 3, 9, 3, 2, 6, 8, 2, 6, 7, 6, 4, 1, 5, 9, 5, 9, 2, 0, 3, 8, 5, 2, 4, 2, 9, 3, 8, 0, 6, 6, 3, 1, 6, 9, 3, 2, 7, 6, 0, 7, 2, 6, 8, 0, 5, 5, 9, 9, 5, 4, 8, 0, 7, 4, 2, 8, 9, 3, 0, 5, 9, 3, 6, 5, 4, 9, 0, 2, 7, 2, 9, 0, 9, 9, 2, 6, 4, 3, 6, 9, 7, 6, 1, 6, 0, 6, 4, 9, 9, 6, 6, 0, 2, 2, 6, 6, 3, 8, 8, 1, 0, 9, 3, 9, 8, 5, 6, 4, 8, 4, 3, 5, 0, 7, 2, 2, 3, 8, 3, 2, 5, 9, 2, 7, 1, 0, 5, 6, 0, 4};
clock_t begin, end;
double time_spent_omp;
double time_spent;
begin = omp_get_wtime();
/* here, do your time-consuming job */
#pragma omp parallel for private(temp)
for(j=0;j<1000;j++){
temp = arr[j];
for(i=0;i<temp;temp--)
result[j]=result[j]*temp;
}
end = omp_get_wtime();
time_spent_omp = (double)(end - begin) / CLOCKS_PER_SEC;
begin = omp_get_wtime();
/* here, do your time-consuming job */
for(j=0;j<1000;j++){
temp = arr[j];
for(i=0;i<temp;temp--)
result[j]=result[j]*temp;
}
end = omp_get_wtime();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("\n\n Time to process: %f --- Time to process with OPENMP %f",time_spent, time_spent_omp);
This should give you a better idea about how it is working.

Reduce array to set number of items? [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 8 years ago.
Improve this question
I have a Ruby array of 300 items. I want to reduce that array down to a set number of items, evenly picked from the array.
The number of items in the array will not be the same every time, nor will the number of items needed.
Something like this:
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
num_of_items = 4
final_arr = [0, 5, 10, 15]
You can use Enumerable#each_slice
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
num_of_items = 4
#=> 4
arr.each_slice(arr.size/num_of_items + 1).map(&:first)
#=> [0, 5, 10, 15]
arr = (0..16).to_a
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
num_of_items = 5
#=> 5
arr.each_slice(arr.size/num_of_items + 1).map(&:first)
#=> [0, 4, 8, 12, 16]
OR
Numeric#step
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
num_of_items = 4
#=> 4
arr.first.step(arr.size, arr.size/num_of_items + 1).map { |i| arr[i] }
#=> [0, 5, 10, 15]
arr = (0..16).to_a
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
num_of_items = 5
#=> 5
arr.first.step(arr.size, arr.size/num_of_items + 1).map { |i| arr[i] }
#=> [0, 4, 8, 12, 16]
If you're picking a given number of items at random from this array, use sample -
$ arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
$ arr.sample(5)
=> [1, 3, 5, 4, 12]
$ arr.sample(5)
=> [15, 6, 13, 5, 11]
If the goal of your algorithm is exactly as shown above, you could use in_groups_of, then grab the first element of each child array:
1.9.3p484 :014 > num_of_items = 5
=> 5
1.9.3p484 :011 > arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
1.9.3p484 :012 > arr.in_groups_of(num_of_items)
=> [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, nil, nil, nil, nil]]
1.9.3p484 :013 > arr.in_groups_of(num_of_items).map(&:first)
=> [0, 5, 10, 15]

Resources