JavaScript(E6)79 82
F=(n,t,
d=n+n*~-n/4-t/2,
l=1,
q=[for(x of Array(n))d<n--?++l:(d+=~n,--l)]
)=>d?[]:q
総当たりやすべてのタプルの列挙は不要です。
長さnのシーケンスをn -1ステップとして参照します。各ステップは増分または減分されます。
インクリメントはデクリメントにしか交換できず、合計は2ずつ変化するため、任意の長さに対して、合計は常に偶数または常に奇数になります。
すべての増分があるため、シーケンスは0、1、2、3、...、n-1であり、合計は(n-1)* n / 2であることがわかります。
最後のステップを変更すると、合計が2変化します。最後のステップの重量は2です。
次のステップから最後のステップを変更すると、合計が4変化するため、最後のステップの重量は4になります。これは、これまでの連続ステップが部分合計に基づいているためです。
前のステップを変更すると、合計が6変化するため、最後のステップの重量は6です(8ではなく、2進数ではありません)。
...
最初のステップの重量を変更する(n-1)* 2
アルゴリズム
Find the max sum (all increments)
Find the difference with the target sum (if it's not even, no solution)
Seq[0] is 0
For each step
Compare current difference with the step weight
if is less
we have an increment here, seq[i] = seq[i-1]+1
else
we have a decrement here, seq[i] = seq[i-1]-1.
Subtract we current weight from the current diff.
If remaining diff == 0, solution is Seq[]. Else no solution
未ゴルフコード
F=(len,target)=>{
max=(len-1)*len/2
delta = max-target
seq = [last=0]
sum = 0
weight=(len-1)*2
while (--len > 0)
{
if (delta >= weight)
{
--last
delta -= weight;
}
else
{
++last
}
sum += last
seq.push(last);
weight -= 2;
}
if (delta) return [];
console.log(sum) // to verify
return seq
}
Firefox / FireBugコンソールでテストする
F(8,4)
出力
[0, -1, 0, -1, 0, 1, 2, 3]
(l-1)*l/2
、間のすべての数値であり-(l-1)*l/2
、と同じパリティを持っているという証拠があります(l-1)*l/2
。