我在為一個看似簡單的遞回函式找到正確的邏輯時遇到了麻煩。(最終目標是將不同長度的文本包裹在不同大小的圓圈內,松散地基于Knuth 的(Tex)演算法......我想我只是盯著這個太久了。)
我堅持將我的靜態函式更改為動態版本,因此我可以列出所有可能的組合,這些組合n可以將單詞拆分為任意數量的行(陣列L[])。
- 每行必須至少包含 1 個單詞
- 這些是句子,所以順序很重要!(我們可以假設
L.length <= n < 0)
例如,將5 個單詞(0-4) 分成3 行(0-2),所有 6 種組合都是:
Line0 Line1 Line2
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
...我可以通過一個簡單的嵌套回圈函式獲得:
//for 3 lines (L[0] to L[2])
const n=5; //number of words
var L=[0], ret=[]; //always starts at word#0 on line#0
for(L[1]=L[0] 1; L[1]<n; L[1] ){ // line#1
for(L[2]=L[1] 1; L[2]<n; L[2] ){ // line#2
ret.push( L );
}
} // returns array of combinations of the start word# for each line,
console.log( ret ); // like: [[0,1,2],[0,1,3],[0,1,4],[0,2,3],[0,2,4],[0,3,4]] ??
這有效(匹配上面的示例組合)...但僅硬編碼 3 行。
因此,我試圖將其重寫為遞回函式,以便行數(和單詞)可以動態更改。
任何幫助表示贊賞。
uj5u.com熱心網友回復:
一種方法是將元素之間的空間視為可移動的邊界。如果我們有單詞a- e,并且我們想將它們分成三個非空序列,那么我們需要選擇其中的兩個空格(隱含的空格總是在兩端。)
a b c d e indices words
--------------------------------------------
| | [1, 2] (a, b, cde)
| | [1, 3] (a, bc, de)
| | [1, 4] (a, bcd, e)
| | [2, 3] (ab, c, de)
| | [2, 4] (ab, cd, e)
| | [3, 4] (abc, d, e)
--------------------------------------------
0 1 2 3 4 Infinity
我們可以將這些邊界與原始陣列一起使用,以相當容易地重建您的單詞集合。
所以困難的問題是找到這些邊界集。但現在這是從四個選項中選擇兩個元素的問題(一般來說,n - 1從words .length - 1選項中選擇選項),這是一個眾所周知的問題。使用它的遞回版本和兩個次要的輔助函式,我們可以這樣寫:
const inPairs = (xs) => xs .slice (1) .map ((x, i) => [xs [i], x])
const range = (lo, hi) => Array .from ({length: hi - lo}, (_, i) => i lo)
const choose = (n) => (xs) =>
n < 1 || n > xs .length
? []
: n == 1
? [...xs .map (x => [x])]
: [
...choose (n - 1) (xs .slice (1)) .map (ys => [xs [0], ...ys]),
...choose (n) (xs .slice (1))
]
const wordBreaks = (ws) => (n) =>
choose (n - 1) (range (1, ws .length)) .map (
(ns) => inPairs ([0, ...ns, Infinity]) .map(([a, b]) => ws .slice (a, b))
)
console .log (wordBreaks (['Simplicity', 'is', 'the', 'ultimate', 'sophistication']) (3))
.as-console-wrapper {max-height: 100% !important; top: 0}
幫手是相當微不足道的。
toPairs將陣列分組為連續對的集合:toPairs (['a', 'b', 'c', 'd']) //=> [['a', 'b'], ['b', 'c'], ['c', 'd']]rangecreates an integer range, inclusive on the left, exclusive on the right:range (3, 12) //=> [3, 4, 5, 6, 7, 8, 9, 10, 11]
The important function here is choose, which collects every set of n items from an array of values.
choose (2) (['a', 'b', 'c', 'd']) //=>
// [['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'c'], ['b', 'd'], ['c', 'd']]
The main function is wordBreaks. It uses range to get get those interstitial indices from the diagram, then uses choose to select n - 1 of those indices, giving us something like [[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]]. Each one of these is wrapped to include 0 and Infinity as well, so that [1, 3, 4] becomes [0, 1, 3, 4, Infinity]. We use toPairs to split this into [[0, 1], [1, 3], [3, 4], [4, Infinity]], then uses those as slice boundaries on our original array, turning ["Here's", "looking", "at", "you", "kid"] into [["Here's"], ["looking", "at"], ["you"], ["kid"]]. And we do this for every collection of indices.
If we add a little display function, we can break a seven-word Shakespeare quote into four segments, like this:
const display = (xss) => console .log (
(xss .map (xs => `["${xs .map (x => x .join (' ')) .join ('", "')}"]`) .join ('\n'))
)
display (wordBreaks (['Now', 'is', 'the', 'winter', 'of', 'our', 'discontent']) (4))
to get
["Now", "is", "the", "winter of our discontent"]
["Now", "is", "the winter", "of our discontent"]
["Now", "is", "the winter of", "our discontent"]
["Now", "is", "the winter of our", "discontent"]
["Now", "is the", "winter", "of our discontent"]
["Now", "is the", "winter of", "our discontent"]
["Now", "is the", "winter of our", "discontent"]
["Now", "is the winter", "of", "our discontent"]
["Now", "is the winter", "of our", "discontent"]
["Now", "is the winter of", "our", "discontent"]
["Now is", "the", "winter", "of our discontent"]
["Now is", "the", "winter of", "our discontent"]
["Now is", "the", "winter of our", "discontent"]
["Now is", "the winter", "of", "our discontent"]
["Now is", "the winter", "of our", "discontent"]
["Now is", "the winter of", "our", "discontent"]
["Now is the", "winter", "of", "our discontent"]
["Now is the", "winter", "of our", "discontent"]
["Now is the", "winter of", "our", "discontent"]
["Now is the winter", "of", "our", "discontent"]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/359898.html
標籤:javascript 递归 组合 排列 自动换行
上一篇:如何在React中遞回渲染帖子
