203 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			203 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | ||
|  | id: 5eb3e4a21f462f409d656c73 | ||
|  | title: 自己参照数列 | ||
|  | challengeType: 5 | ||
|  | forumTopicId: 385317 | ||
|  | dashedName: self-referential-sequence | ||
|  | --- | ||
|  | 
 | ||
|  | # --description--
 | ||
|  | 
 | ||
|  | 自己参照数列を生成する方法はいくつかあります。 特によく知られた例の 1 つである ( [読み上げ数列](https://rosettacode.org/wiki/Look-and-say sequence)) は、正の整数から始め、次いで隣接する同じ数字のまとまりを数え上げ、連結することにより、次の項を生成します。 | ||
|  | 
 | ||
|  | <pre>0, 10, 1110, 3110, 132110, 1113122110, 311311222110 ...</pre> | ||
|  | 
 | ||
|  | 生成された項は幾何学的に成長し、決して収束しません。 | ||
|  | 
 | ||
|  | 自己参照数列を生成するもう一つの方法は、前の項を要約することです。 | ||
|  | 
 | ||
|  | 同じ数字がいくつあるかを数え、ソートした各数字の個数と数字を連結します。 最初の 5 つの項は、前の数列と同じであることに注意してください。 | ||
|  | 
 | ||
|  | <pre>0, 10, 1110, 3110, 132110, 13123110, 23124110 ...</pre> | ||
|  | 
 | ||
|  | 数字は最大から最小への順にソートします。 前の項に現れない数字はカウントに含めません。 | ||
|  | 
 | ||
|  | シード値に応じて、このように生成された数列は常に安定値または短周期パターンに収束します (この場合の収束とは、要素が以前に現れた要素と一致することを意味します)。 上記のシード値が 0 の数列は、11回繰り返すと安定値 1433223110 に収束します。 最も迅速に収束するシード値は22です。 最初の要素の後に安定します。 (次の要素の22はすでに現れています)。 | ||
|  | 
 | ||
|  | # --instructions--
 | ||
|  | 
 | ||
|  | シード値をパラメータとして取り、収束するまで自己参照数列を生成し、それを配列として返す関数を記述してください。 | ||
|  | 
 | ||
|  | # --hints--
 | ||
|  | 
 | ||
|  | `selfReferential` は関数とします。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert(typeof selfReferential === 'function'); | ||
|  | ``` | ||
|  | 
 | ||
|  | `selfReferential(40)` は配列を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert(Array.isArray(selfReferential(40))); | ||
|  | ``` | ||
|  | 
 | ||
|  | `selfReferential(40)` は `["40", "1410", "142110", "14123110", "1413124110", "2413125110", "151413224110", "152413225110", "251413324110", "152423224110", "152413423110"]` を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual(selfReferential(40), [ | ||
|  |   '40', | ||
|  |   '1410', | ||
|  |   '142110', | ||
|  |   '14123110', | ||
|  |   '1413124110', | ||
|  |   '2413125110', | ||
|  |   '151413224110', | ||
|  |   '152413225110', | ||
|  |   '251413324110', | ||
|  |   '152423224110', | ||
|  |   '152413423110' | ||
|  | ]); | ||
|  | ``` | ||
|  | 
 | ||
|  | `selfReferential(132110)` は `["132110", "13123110", "23124110", "1413223110", "1423224110", "2413323110", "1433223110"]` を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual(selfReferential(132110), [ | ||
|  |   '132110', | ||
|  |   '13123110', | ||
|  |   '23124110', | ||
|  |   '1413223110', | ||
|  |   '1423224110', | ||
|  |   '2413323110', | ||
|  |   '1433223110' | ||
|  | ]); | ||
|  | ``` | ||
|  | 
 | ||
|  | `selfReferential(132211)` は `["132211", "132231", "232221", "134211", "14131231", "14231241", "24132231", "14233221"]` を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual(selfReferential(132211), [ | ||
|  |   '132211', | ||
|  |   '132231', | ||
|  |   '232221', | ||
|  |   '134211', | ||
|  |   '14131231', | ||
|  |   '14231241', | ||
|  |   '24132231', | ||
|  |   '14233221' | ||
|  | ]); | ||
|  | ``` | ||
|  | 
 | ||
|  | `selfReferential(1413223110)` は `["1413223110", "1423224110", "2413323110", "1433223110"]` を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual(selfReferential(1413223110), [ | ||
|  |   '1413223110', | ||
|  |   '1423224110', | ||
|  |   '2413323110', | ||
|  |   '1433223110' | ||
|  | ]); | ||
|  | ``` | ||
|  | 
 | ||
|  | `selfReferential(251413126110)` は `["251413126110", "16151413225110", "16251413226110", "26151413325110", "16251423225110", "16251413424110", "16153413225110"]` を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.deepEqual(selfReferential(251413126110), [ | ||
|  |   '251413126110', | ||
|  |   '16151413225110', | ||
|  |   '16251413226110', | ||
|  |   '26151413325110', | ||
|  |   '16251423225110', | ||
|  |   '16251413424110', | ||
|  |   '16153413225110' | ||
|  | ]); | ||
|  | ``` | ||
|  | 
 | ||
|  | # --seed--
 | ||
|  | 
 | ||
|  | ## --seed-contents--
 | ||
|  | 
 | ||
|  | ```js | ||
|  | function selfReferential(n) { | ||
|  | 
 | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | # --solutions--
 | ||
|  | 
 | ||
|  | ```js | ||
|  | function selfReferential(n) { | ||
|  |   var descending, | ||
|  |     i, | ||
|  |     incr, | ||
|  |     j, | ||
|  |     max_i, | ||
|  |     max_len, | ||
|  |     max_seq, | ||
|  |     seq, | ||
|  |     sequence, | ||
|  |     indexOf = | ||
|  |       [].indexOf || | ||
|  |       function(item) { | ||
|  |         for (var i = 0, l = this.length; i < l; i++) { | ||
|  |           if (i in this && this[i] === item) return i; | ||
|  |         } | ||
|  |         return -1; | ||
|  |       }; | ||
|  | 
 | ||
|  |   sequence = function(n) { | ||
|  |     var c, cnt, cnts, d, digit, i, j, l, len, new_cnts, ref, s, seq; | ||
|  |     cnts = {}; | ||
|  |     ref = n.toString(); | ||
|  |     for (j = 0, len = ref.length; j < len; j++) { | ||
|  |       c = ref[j]; | ||
|  |       d = parseInt(c); | ||
|  |       incr(cnts, d); | ||
|  |     } | ||
|  |     seq = [ref]; | ||
|  |     while (true) { | ||
|  |       s = ''; | ||
|  |       for (i = l = 9; l >= 0; i = --l) { | ||
|  |         if (cnts[i]) { | ||
|  |           s += '' + cnts[i] + i; | ||
|  |         } | ||
|  |       } | ||
|  |       if (indexOf.call(seq, s) >= 0) { | ||
|  |         break; | ||
|  |       } | ||
|  |       seq.push(s); | ||
|  |       new_cnts = {}; | ||
|  |       for (digit in cnts) { | ||
|  |         cnt = cnts[digit]; | ||
|  |         incr(new_cnts, cnt); | ||
|  |         incr(new_cnts, digit); | ||
|  |       } | ||
|  |       cnts = new_cnts; | ||
|  |     } | ||
|  |     return seq; | ||
|  |   }; | ||
|  | 
 | ||
|  |   incr = function(h, k) { | ||
|  |     if (h[k] == null) { | ||
|  |       h[k] = 0; | ||
|  |     } | ||
|  |     return (h[k] += 1); | ||
|  |   }; | ||
|  | 
 | ||
|  |   descending = function(n) { | ||
|  |     var tens; | ||
|  |     if (n < 10) { | ||
|  |       return true; | ||
|  |     } | ||
|  |     tens = n / 10; | ||
|  |     if (n % 10 > tens % 10) { | ||
|  |       return false; | ||
|  |     } | ||
|  |     return descending(tens); | ||
|  |   }; | ||
|  | 
 | ||
|  |   return sequence(n); | ||
|  | } | ||
|  | ``` |