자바 스크립트 (ES6), 329
콤비 네이터가 내장되어 있지 않은 언어에는 쉬운 일이 아닙니다.
아마 더 엄숙한 골프.
참고 : 단일 요소가있는 파티션은 항상 유용하지 않기 때문에 모든 파티션의 크기는 2 이상입니다.
Example: [1] [2 3 4] // can take 1 or 2 or 4
Better: [1 2] [3 4] // can take 3 too
a=>{G=(v,i,u=v)=>{if(i--){for(;r[i]=--u;)if(G(u,i))return 1;}else for(w=[...r,n=l].map((x,i)=>a.slice(z,z=x-~i),z=0),y=w.join`;`;w.map(b=>[0,1].map(q=>(x=b[q*=~-b.length])&&(t[x]?([c,p]=t[x],n-=2,p?c.pop():c.shift(),q?b.pop():b.shift()):t[x]=[b,q])),c=0,t=[]),c;)if(!n)return 1};for(l=a.length,r=[],k=0;!G(l-k-1,k);k++);return y}
부분 설명
(매우 장황하지만 설명하기가 어렵다는 것을 알았습니다. 결국 "모두 정리"를 건너 뛰십시오.
배열의 모든 가능한 분할을 열거하는 재귀 함수
// v: array length
// i number of splits
// fill the global array r that must exists
G=(v,i,u=v)=>
{
if(i--)
{
for(;r[i]=--u;)
G(u,i)
}
else
{
// the current split position are in r, ready to use
// for instance...
parts = [...r,a.length].map(x=>a.slice(z,z=x),z=0)
console.log(r, parts)
}
};
r=[]
a=['A','B','C','D']
G(4, 2)
// output in console (firebug)
[2, 3] [["A", "B"], ["C"], ["D"]]
[1, 3] [["A"], ["B", "C"], ["D"]]
[1, 2] [["A"], ["B"], ["C", "D"]]
이제 크기가 2 이상인 파티션이 필요하므로이 함수를 상당히 다른 매개 변수와 함께 사용해야합니다. 매개 변수 v는 "배열 크기-원하는 파티션 수-1"입니다. 그런 다음 약간 다른 방식으로 파티션을 만들어야합니다.
// Same call (4,2), same r, but the array b is of size 7
part = [...r,b.length].map((x,i)=>
b.slice(z,z=x+i+1) // add 1 more element to each partition
,z=0))
// output in console (firebug)
[2, 3] [["A", "B", "C"], ["D", "E"], ["F", "G"]]
[1, 3] [["A", "B"], ["C", "D", "E"], ["F", "G"]]
[1, 2] [["A", "B"], ["C", "D"], ["E", "F", "G"]]
따라서 분할 없음, 1 분할, 2 분할 등의 파티션 목록을 열거 할 수 있습니다. 작업 파티션을 찾으면 중지하고 찾은 결과를 출력합니다.
확인하려면 파티션 목록을 스캔하고 각 값의 시작과 끝에있는 값을 기록한 후 응답 된 값을 찾으면 제거하십시오. 마지막으로 아무것도 제거 할 수 없을 때까지 반복하십시오. 모든 쌍이 제거되면이 파티션에 적합합니다.
t = []; // array to note the repeated values
// t[x] == [
// subarray holding value x,
// position of value x (I care zero or nonzero)
// ]
n = a.length // counter start, must reach 0
// remember part just in case, because this check will destroy it
result = part.join(';') // a string representation for return value
do
{
// in the golfed code there is a forr loop
// all this body is inside the for condition
c = 0; // init c to a falsy, if a pair is found c becomes truthy
part.forEach(b=> // b: array, current partition
[0,1].forEach(q=> ( // exec for 0 (start), 1 (end)
q *= b.length-1, // now q is the correct index
x = b[q]) // x is the value at start or end
x && ( // b could be empty, check that x is not 'undefined'
t[x] ? // is there a value in t at position x?
( // yes, remove the pair
n-=2, // pair found, decrement counter
[c, p] = t[x], // get stored array and position
p ? c.pop() : c.shift(), // remove from c at start or end
q ? b.pop() : b.shift() // remove twin value from b
)
: // no, remember the value in t
t[x] = [b, q]
)) // end [0,1].forEach
) // end part.forEach
}
while (c) // repeat until nothing can be removed
if(!n) return 1 // wow, result found (in 'result' variable)
그런 다음 누락 된 부분은 G 함수를 루프 계산하여 파티션 수를 늘리는 것입니다. 결과가 발견되면 루프가 종료됩니다.
다 합쳐
F=a=>{
G=(v,i,u=v)=>{
if (i--)
{
for(; r[i]=--u; )
if (G(u,i))
return 1;
}
else
{
w = [...r,n=l].map((x,i)=>a.slice(z, z = x-~i), z = 0);
y = w.join`;`;
for(; // almost all the for body is inside the condition
w.map(b=>
[0,1].map(q=>
(x=b[q*=~-b.length])
&&(t[x]
?([c,p]=t[x],n-=2,
p?c.pop():c.shift(),
q?b.pop():b.shift())
:t[x]=[b,q])) // end [0,1].map
,c=0,t=[] // init variables for w.map
),c; // the loop condition is on c
)
if(!n)return 1 // this is the for body
}
};
for(l = a.length, r = [], k = 0; !G(l-k-1, k); k++);
return y
}
테스트
F=a=>{G=(v,i,u=v)=>{if(i--){for(;r[i]=--u;)if(G(u,i))return 1;}else for(w=[...r,n=l].map((x,i)=>a.slice(z,z=x-~i),z=0),y=w.join`;`;w.map(b=>[0,1].map(q=>(x=b[q*=~-b.length])&&(t[x]?([c,p]=t[x],n-=2,p?c.pop():c.shift(),q?b.pop():b.shift()):t[x]=[b,q])),c=0,t=[]),c;)if(!n)return 1};for(l=a.length,r=[],k=0;!G(l-k-1,k);k++);return y}
console.log=x=>O.textContent+=x+'\n'
TestData=[[1,1],[1,2,1,2],[1,3,2,4,3,2,1,4],[1,2,3,4,3,4,1,2],[1,1,2,2,3,3],[4,3,4,2,2,1,1,3]]
TestData.forEach(t=>console.log(t+' -> '+F(t)))
function RandomTest() {
var l=I.value*2
var a=[...Array(l)].map((_,i)=>1+i/2|0)
a.map((v,i)=>a[a[i]=a[j=0|i+Math.random()*(a.length-i)],j]=v) // shuffle
Q.textContent=a+''+'\n\n'+F(a).replace(/;/g, ';\n') // better readability
}
Base test
<pre id=O></pre>
Random test. Number of pairs: <input id=I value=15><button onclick="RandomTest()">-></button>
<pre id=Q></pre>