Here I found question which was formulated as follows, but I develop it and ask new questions about optimization (which need of course new different solutions). We have array of arbitrary number of elements - 3d vectors - for example:
let a=[ [0,1,2], [1,0,2], [1,1,1], [1,2,0 ], [2,0,1 ], [2,1,0 ] ];
And we want to remove elements from that list, which have duplicate value on i-th index with other elements. This problem can have more than one solution:
- solution with 3 elements:
[0,1,2],[1,2,0],[2,0,1]
- solution with 2 elements:
[1,0,2],[2,1,0]
As you can see, the solution has this property that each solution element have unique value on i-th index (numbers on i-th position never duplicate) and if we add any other element from array a
to that solution we loose this property. I already create algorithm to find one solution
let a=[[ 0, 1, 2 ], [ 1, 0, 2 ], [ 1, 1, 1 ], [ 1, 2, 0 ], [ 2, 0, 1 ], [ 2, 1, 0 ] ,];
let t=[{},{},{}];
let d= a.filter(e =>
!e.reduce((g,h,i)=> g||(e[i] in t[i]),false) && e.map((x,i) => t[i][x]=x)
);
console.log(JSON.stringify(d));
But have no Idea how to create non-brute-force algorithm which will find:
- shortest solution
- longest solution
If you not code in js, the detail described algorithm is also acceptable.
Update
As @btilly answer says, the find longest solution is NP-hard problem (similar to 3d-matching). However the question about algorithm finding shortest solution is still open. Below little visualistation showing analogy between question and 3d-matching:
// matching = [[1,2,3], [2,3,4]]; // numbers shod be integers
function draw(divSelector, matching) {
let c = '';
let r = 10,
marginLeft = 40,
marginTop = 40;
let spaceX = 100,
spaceY = 100,
mSizeMin = 10,
mSizeMax = 20;
let max = Math.max(...matching.flat());
let min = Math.min(...matching.flat());
['X', 'Y', 'Z'].forEach((e, i) => {
c += `<text class="text"><tspan x="${marginLeft+i*spaceX}" y="${marginTop-20}">${e}</tspan></text>`
});
if (matching.length > 0) {
[...Array(25)].map((_, i) => i + min).forEach((e, i) => {
c += `<text class="text"><tspan x="${marginLeft-20}" y="${marginTop+i*spaceY}">${min+i}</tspan></text>`
});
}
// matching
matching.forEach((e, j) => {
let x0 = marginLeft + 0 * spaceX,
y0 = marginTop + (e[0] - min) * spaceY;
let x1 = marginLeft + 1 * spaceX,
y1 = marginTop + (e[1] - min) * spaceY;
let x2 = marginLeft + 2 * spaceX,
y2 = marginTop + (e[2] - min) * spaceY;
let st = mSizeMin + (mSizeMax - mSizeMin) * (1 - j / (matching.length - 1)); // matching size
let sc = 127 + (128 * j / (matching.length)) | 0;
sc = `rgb(${sc},${sc},${sc})` // color
let mF = `<path class="matF" d="M ${x0},${y0} L ${x1},${y1} L ${x2},${y2}" style="stroke-width:${st}; stroke:${sc}"/>`
let mB = `<path class="matB" d="M ${x0},${y0} L ${x1},${y1} L ${x2},${y2}" style="stroke-width:${st+2}"/>`
c += mB + mF;
});
// points
for (let i = 0; i < 3; i++) {
for (let j = 0; j <= max - min; j++) {
let x = marginLeft + i * spaceX,
y = marginTop + j * spaceY;
let p = `<path class="point point_${i}" d="M ${x+r/2},${y} A 1,1 0 1 1 ${x-r/2},${y} A 1,1 0 1 1 ${x+r/2},${y} z"/>`;
c += p;
}
}
let s = `<svg height=${2*marginTop+spaceY*(max-min)} width=${2*marginLeft+spaceX*2} xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">${c}</svg>`;
document.querySelector(divSelector).innerHTML = s;
}
function showList(list) {
let s = ''
list.forEach((x, i) => {
s += `<div class="listItem" onclick="removeElement(${i})">[ ${x} ] del</div>`
})
document.getElementById('list').innerHTML = s;
}
let list = [
[0, 1, 2],
[1, 0, 2],
[1, 1, 1],
[1, 2, 0],
[2, 0, 1],
[2, 1, 0]
];
function update() {
let v = document.querySelector('#vec').value
if (!/^ *\d*, *\d*, *\d*$/.test(v)) {
alert('Write 3 separated by comma e.g.: 1,2,3');
return;
}
document.querySelector('#vec').value = '';
nv = v.split(',').map(x => +x);
list.push(nv);
list = list.filter((t = {}, e => !(t[e] = e in t))) //unique
draw('#container', list);
showList(list);
}
function removeElement(i) {
list.splice(i, 1)
refresh(list);
}
function clearAll() {
list = [];
refresh(list);
}
function refresh(list) {
draw('#container', list);
showList(list);
}
refresh(list);
.point {
opacity: 1;
fill: #d40000;
fill-opacity: 1;
fill-rule: evenodd;
stroke: #000000;
stroke-width: 2;
stroke-linecap: butt;
stroke-linejoin: miter;
marker: none;
marker-start: none;
marker-mid: none;
marker-end: none;
stroke-miterlimit: 4;
stroke-dasharray: none;
stroke-dashoffset: 0;
stroke-opacity: 1;
visibility: visible;
display: inline;
overflow: visible;
enable-background: accumulate
}
.point_0 {
fill: #d40000
}
.point_1 {
fill: #00d400
}
.point_2 {
fill: #0000d4
}
.matF {
opacity: 1;
fill: none;
fill-opacity: 1;
fill-rule: evenodd;
stroke: #e6e6e6;
stroke-width: 22;
stroke-linecap: round;
stroke-linejoin: round;
marker: none;
marker-start: none;
marker-mid: none;
marker-end: none;
stroke-miterlimit: 4;
stroke-dasharray: none;
stroke-dashoffset: 0;
stroke-opacity: 1;
visibility: visible;
display: inline;
overflow: visible;
enable-background: accumulate
}
.matB {
opacity: 1;
fill: none;
fill-opacity: 1;
fill-rule: evenodd;
stroke: #000000;
stroke-width: 24;
stroke-linecap: round;
stroke-linejoin: round;
marker: none;
marker-start: none;
marker-mid: none;
marker-end: none;
stroke-miterlimit: 4;
stroke-dasharray: none;
stroke-dashoffset: 0;
stroke-opacity: 1;
visibility: visible;
display: inline;
overflow: visible;
enable-background: accumulate
}
.content {
display: flex;
}
.listItem {
cursor: pointer
}
.text {
font-size: 16px;
font-style: italic;
font-variant: normal;
font-weight: normal;
font-stretch: normal;
text-align: center;
text-anchor: middle;
fill: #000000;
fill-opacity: 1;
stroke: none;
stroke-width: 1px;
stroke-linecap: butt;
stroke-linejoin: miter;
stroke-opacity: 1;
font-family: Sans;
-inkscape-font-specification: Sans Italic
}
Type 3d vector with (positive integer numbers e.g. 1,2,3)<br>
<input id="vec" value="1,2,3">
<button onclick="update()">add</button>
<button onclick="clearAll()">clear all</button>
<div class="content">
<div id='container'>
</div>
<div id='list'>
</div>
</div>
Update 2
I ask question and get answer here and according to it the problem of find the shortest solution is NP-hard (and it is even harder than finding longest solution because for 2D case the longes solution is NOT NP-hard but the smallest solution in 2D is NP-hard).