minizinc: find element in arrray - minizinc
I have two arrays(type: int) of different length. How could I find the closest number in array b for each number in array a(the following does not work though probably because of syntax error):
int: m;
int: n;
array [1..m] of int: a;
array [1..n] of int: b;
array[1..m] of int: results;
results = [abs(a[i] - b[j])| i in 1..m, j in 1..n];
solve minimize results;
output ["Solution: ", show(results)];
(It always helps with a complete model with as much information as possible, e.g. the values of "m" and "n" and other known/fixed values. Also, mention of the error messages helps in general.)
There are a couple of unknown things in your model, so I have to guess a little.
I guess that "results" really should be a single decision variable, and not an array as you defined it. Then you can write
var int: results = sum([abs(a[i] - b[j])| i in 1..m, j in 1..n]);
or
var int: results;
...
constraint results = sum([abs(a[i] - b[j])| i in 1..m, j in 1..n]);
Also, as it stand the model is not especially interesting since it just define two constant arrays "a" and "b" (which must be filled with constant values). I assume that at least one of them are meant to be decision variables. An array of decision variable must be declared with "var int" (or better: something like "var 1..size" where 1..size is the domain of possible values in the array).
Here is an example of a working model, which may or may not be something like what you have in mind:
int: m = 10;
int: n = 10;
array [1..m] of int: a = [1,2,3,4,5,6,7,8,9,10];
array [1..n] of var 1..10: b;
var int: results = sum([abs(a[i] - b[j])| i in 1..m, j in 1..n]);
solve minimize results;
output [
"Solution: ", show(results),"\n",
"a: ", show(a), "\n",
"b: ", show(b), "\n",
];
Update 2015-11-19:
I'm not sure I've understand the requirements completely, but here is a variant. Note that the sum loop don't use the "b" array at all, just "a" and "results". To ensure that the values in "results" are selected from "b" the domain of "results" are simply the set of the values in "b".
int: m = 10;
int: n = 10;
array [1..m] of int: a = [1,2,3,4,5,6,7,8,9,10];
array [1..n] of int: b = [5,6,13,14,15,16,17,18,19,20];
% decision variables
% values only from b
array[1..m] of var {b[i] | i in 1..n}: results;
var int: z; % to minimize
constraint
z >= 0 /\
z = sum(i in 1..m) (
sum(j in 1..m) (abs(a[i]-results[j]))
% (abs(a[i]-results[i])) % alternative interpretation (see below)
)
;
solve minimize z;
output [
"z: ", show(z), "\n",
"results: ", show(results),"\n",
"a: ", show(a), "\n",
"b: ", show(b), "\n",
];
Gecode has this for the optimal solution:
z: 250
results: [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b: [5, 6, 13, 14, 15, 16, 17, 18, 19, 20]
Another solver (Opturion CPX) has a solution more similar to your variant:
z: 250
results: [6, 6, 5, 5, 5, 6, 6, 6, 5, 5]
a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b: [5, 6, 13, 14, 15, 16, 17, 18, 19, 20]
Note that both solutions has the same optimal objective value ("z") of 250.
There is, however, an alternative interpretation of the requirement (from your comment):
for each element in a, select a corresponding value from b - this
value has to be the closest in value to each element in a.
where each value in "results" corresponds just the the value in "a" with the same index ("i") , i.e.
% ...
constraint
z >= 0 /\
z = sum(i in 1..m) (
(abs(a[i]-results[i]))
)
;
The solution then is (Gecode):
z: 19
results: [5, 5, 5, 5, 5, 6, 6, 6, 6, 13]
a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b: [5, 6, 13, 14, 15, 16, 17, 18, 19, 20]
The last value in "results" (13) is then chosen since it's nearer to 10 (last element in "a").
Update 2 (2015-11-20)
Regarding the second comment, about a 2D (not a 3D version you wrote), here's a model. It's based on the second interpretation of the model above. Extending it to larger dimensions is just a matter of changing the dimensions and adding the loop variables.
Note that this assumes - perhaps contrary to your original question - that the dimensions of "a" and "results" are identical. If they are not, the the second interpretation can not be the one you intend. Also, I changed the values in "a" and "b" to make it more interesting. :-)
int: m = 3;
int: n = 3;
array [1..m,1..n] of int: a = [|1,2,3|4,5,6|7,8,9|];
array [1..m,1..n] of int: b = [|5,6,13|14,15,16,|7,18,19|];
% decision variables
% values only from b
array[1..m,1..n] of var {b[i,j] | i in 1..m, j in 1..n}: results;
var int: z;
constraint
z >= 0 /\
z = sum(i in 1..m, j in 1..n) (
(abs(a[i,j]-results[i,j]))
)
;
solve minimize z;
output [ "z: ", show(z), "\n" ]
++["results:"]++
[
if j = 1 then "\n" else " " endif ++
show_int(2,results[i,j])
| i in 1..m, j in 1..n
]
++["\na:"]++
[
if j = 1 then "\n" else " " endif ++
show_int(2,a[i,j])
| i in 1..m, j in 1..n
]
++["\nb:"]++
[
if j = 1 then "\n" else " " endif ++
show_int(2,b[i,j])
| i in 1..m, j in 1..n
];
One optimal solution of this is this:
z: 13
results:
5 5 5
5 5 6
7 7 7
a:
1 2 3
4 5 6
7 8 9
b:
5 6 13
14 15 16
7 18 19
Related
Contract m-repeated numbers in list to n-repeated (n<m) in place in O(1) space
I want to write a python 3.7 function that has a sorted list of numbers as an input, and a number n which is the max number each one of the integers can be repeated and modifies the list in place, so that any numbers that are repeated more than n times, would be cut to n repeats, and it should be done in O(1) space, no additional data structures allowed (e.g. set()). Special case - remove duplicates where n = 1. Example: dup_list = [1, 1, 1, 2, 3, 7, 7, 7, 7, 12] dedup(dup_list, n = 1) print(dup_list) [1, 2, 3, 7, 12] dup_list = [1, 1, 1, 2, 3, 7, 7, 7, 7, 12] dedup(dup_list, n = 2) print(dup_list) [1, 1, 2, 3, 7, 7, 12] dup_list = [1, 1, 1, 2, 3, 7, 7, 7, 7, 12] dedup(dup_list, n = 3) print(dup_list) [1, 1, 1, 2, 3, 7, 7, 7, 12] Case n = 1 is easy, the code is below (code is taken from Elements of Prograqmming Interviews, 2008, page 49 except the last line return dup_list[:write_index]): def dedup(dup_list): if not dup_list: return 0 write_index = 1 for i in range(1, len(dup_list)): if dup_list[write_index-1] != dup_list[i]: dup_list[write_index] = dup_list[i] write_index += 1 return dup_list[:write_index]
This should work: def dedup2(dup_list, n): count = 1 list_len = len(dup_list) i = 1 while i < list_len: if dup_list[i - 1] != dup_list[i]: count = 1 else: count += 1 if count > n: del(dup_list[i]) i -= 1 list_len -= 1 i += 1 return dup_list print(dedup2([1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 8, 9], 1))
In Swift 5, How can i check if the input 2d array [[Int]] is matrix M x M not M x N
I have an input arr: [[Int]] How can i check if this arr is M x M So, it should looks like: [1,2,3] [4,5,6] [7,8,9] not to be M x N such as: [1,2,3] [4,5] [6,7,8,9] I have tried arr.count but it return 3 in the previous two cases, because it return the number of sub arrays not its their counts too.
You have to check if all “inner” arrays have the same length as the “outer” array. This is conveniently done with the allSatisfy method: func isSquareMatrix<T>(_ m: [[T]]) -> Bool { let dim = m.count return m.allSatisfy { $0.count == dim } } Example: print(isSquareMatrix([[1, 2, 3], [3, 5, 6], [7, 8, 9]])) // true print(isSquareMatrix([[1, 2, 3], [4, 5], [6, 7, 8, 9]])) // false The above function is generic so that it can be used with arbitrary element types, not only with [[Int]]: print(isSquareMatrix([[1.0, 2.0], [3.0, 4.0]])) // true
Map and split values in array
How I can map a array and, in same closure, split the values in two variables? This code work, but, I want use only one closure, not three. let array = [1, 2, 3, 4] let a = array.map { v -> (Int, Int) in (v * 2, v * 10) } let x = a.map { $0.0 } let y = a.map { $0.1 }
Here's a possibly less readable, but arguably more functional-style solution (immutable arrays, no for-each loop, pure function that only acts on its inputs and doesn't create side effects outside the closure): let array = [1, 2, 3, 4] let (x, y) = array.reduce(([Int](), [Int]())){ (result, int) in (result.0 + [int*2], result.1 + [int*10]) } print(x) // [2, 4, 6, 8] print(y) // [10, 20, 30, 40] It also meets your requirement of using just one closure
Try this: let array = [1, 2, 3, 4] var x = [Int]() var y = [Int]() array.forEach() { x.append($0 * 2) y.append($0 * 10) } print(x[0]) // 2 print(y[0]) // 10 ...
You can use tuple assignment to achieve this: let array = [1, 2, 3, 4] let (x, y) = (array.map{$0 * 2}, array.map{$0 * 10}) print(x, y)
Is it possible to match N elements with a coffeescript splat?
Is it possible to specify how many elements a splat should match? Something like: foo = [1, 2, 3, 4, 5, 6] [firstThree...(3), fourth, rest...] = foo console.log firstThree // [1, 2, 3] console.log forth // 4 console.log rest // [5, 6]
As far as I know there is no way of adding a limit to the amount of arguments a splat can take. But you can use ranges(search for range in the Loops and Comprehensions Docs) to get a similar syntax in your destructuring assignment: foo = [1, 2, 3, 4, 5, 6] [firstThree, fourth, rest] = [foo[0..2], foo[3], foo[4..-1]] firstThree # => [1, 2, 3] fourth # => 4 rest # => [5, 6]
Object range with conditions
In groovy I can write def n = 10 print 1..<n Output: [1, 2, 3, 4, 5, 6, 7, 8, 9] Are there other language that allow to specify range with conditions? examples def n = 10 print 1<=..n Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def n = -2 print 1<=..n Output: [1] def n = -2 print 1..n Output: [1, 0, -1, -2]
Python has the range() method which does a similar thing. While it does not use operators for the condition you can specify a start value, stop value and step value. It then creates a list containing all values starting with the start value, then start+step, ... until it reaches the end value (which is not included).