112 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			112 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | ||
|  | id: 5900f37a1000cf542c50fe8d | ||
|  | title: '問題 14: 最長のコラッツ数列' | ||
|  | challengeType: 5 | ||
|  | forumTopicId: 301768 | ||
|  | dashedName: problem-14-longest-collatz-sequence | ||
|  | --- | ||
|  | 
 | ||
|  | # --description--
 | ||
|  | 
 | ||
|  | 正の整数の集合について、次の反復数列が定義されています。 | ||
|  | 
 | ||
|  | <div style='padding-left: 4em;'><var>n</var> → <var>n</var>/2 (<var>n</var> は偶数)</div> | ||
|  | 
 | ||
|  | <div style='padding-left: 4em;'><var>n</var> → 3<var>n</var> + 1 (<var>n</var> は奇数)</div> | ||
|  | 
 | ||
|  | 13 から始めて上のルールに従うと、次の数列になります。 | ||
|  | 
 | ||
|  | <div style='text-align: center;'>13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1</div> | ||
|  | 
 | ||
|  | この数列 (13 から始まり、1 で終わる) に 10 個の項が含まれていることが分かります。 まだ証明されていませんが (コラッツ問題)、どの数から始めても 1 で終わると考えられています。 | ||
|  | 
 | ||
|  | 与えられた `limit` より小さい数のうち、どの数から始めると連鎖が最も長くなりますか。 | ||
|  | 
 | ||
|  | **注:** 連鎖が始まった後であれば項が `limit` を超えても構いません。 | ||
|  | 
 | ||
|  | # --hints--
 | ||
|  | 
 | ||
|  | `longestCollatzSequence(14)` は数値を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert(typeof longestCollatzSequence(14) === 'number'); | ||
|  | ``` | ||
|  | 
 | ||
|  | `longestCollatzSequence(14)` は 9 を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.strictEqual(longestCollatzSequence(14), 9); | ||
|  | ``` | ||
|  | 
 | ||
|  | `longestCollatzSequence(5847)` は 3711 を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.strictEqual(longestCollatzSequence(5847), 3711); | ||
|  | ``` | ||
|  | 
 | ||
|  | `longestCollatzSequence(46500)` は 35655 を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.strictEqual(longestCollatzSequence(46500), 35655); | ||
|  | ``` | ||
|  | 
 | ||
|  | `longestCollatzSequence(54512)` は 52527 を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.strictEqual(longestCollatzSequence(54512), 52527); | ||
|  | ``` | ||
|  | 
 | ||
|  | `longestCollatzSequence(100000)` は 77031 を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.strictEqual(longestCollatzSequence(100000), 77031); | ||
|  | ``` | ||
|  | 
 | ||
|  | `longestCollatzSequence(1000000)` は 837799 を返す必要があります。 | ||
|  | 
 | ||
|  | ```js | ||
|  | assert.strictEqual(longestCollatzSequence(1000000), 837799); | ||
|  | ``` | ||
|  | 
 | ||
|  | # --seed--
 | ||
|  | 
 | ||
|  | ## --seed-contents--
 | ||
|  | 
 | ||
|  | ```js | ||
|  | function longestCollatzSequence(limit) { | ||
|  | 
 | ||
|  |   return true; | ||
|  | } | ||
|  | 
 | ||
|  | longestCollatzSequence(14); | ||
|  | ``` | ||
|  | 
 | ||
|  | # --solutions--
 | ||
|  | 
 | ||
|  | ```js | ||
|  | function longestCollatzSequence(limit) { | ||
|  |   let longest = 1; | ||
|  |   let maxLength = 1; | ||
|  |   for (let i = Math.floor(limit / 2); i < limit; i++) { | ||
|  |     let len = colLen(i); | ||
|  |     if (len > maxLength) { | ||
|  |       longest = i; | ||
|  |       maxLength = len; | ||
|  |     } | ||
|  |   } | ||
|  |   return longest; | ||
|  | } | ||
|  | 
 | ||
|  | const knownSequence = { '1': 1 }; | ||
|  | 
 | ||
|  | function colLen(n) { | ||
|  |   if (knownSequence[n]) { | ||
|  |     return knownSequence[n]; | ||
|  |   } else { | ||
|  |     const len = n % 2 === 0 ? colLen(n / 2) + 1 : colLen((3 * n + 1) / 2) + 2; | ||
|  |     knownSequence[n] = len; | ||
|  |     return len; | ||
|  |   } | ||
|  | } | ||
|  | ``` |