chore(i18n,learn): processed translations (#44851)

This commit is contained in:
camperbot
2022-01-21 01:00:18 +05:30
committed by GitHub
parent f866718a3d
commit 5c868af2b8
1696 changed files with 159426 additions and 69 deletions

View File

@ -0,0 +1,150 @@
---
id: a3f503de51cf954ede28891d
title: 対称差を見つける
challengeType: 5
forumTopicId: 301611
dashedName: find-the-symmetric-difference
---
# --description--
2 つの集合の「<dfn>対称差</dfn>」(`△` または `⊕`) という数学用語は、2 つの集合のいずれかにあるが両方にはない要素の集合を意味します。 例えば、集合 `A = {1, 2, 3}` と集合 `B = {2, 3, 4}`の場合、`A △ B = {1, 4}` です。
対称差は二項演算で、すなわち 2 つの要素のみに対する演算です。 そのため、*3 つ*の要素間 (`A △ B △ C`) の対称差を求める式を評価するには、一度に 1 つずつ演算を完了させなければなりません。 したがって、上記の集合 `A``B` に加えて `C = {2, 3}` がある場合、`A △ B △ C = (A △ B) △ C = {1, 4} △ {2, 3} = {1, 2, 3, 4}` です。
# --instructions--
2 つ以上の配列を取りそれらの対称差の配列を返す、1 つの関数を作成してください。 返される配列には一意の値のみ (*重複なし*) が含まれている必要があります。
# --hints--
`sym([1, 2, 3], [5, 2, 1, 4])``[3, 4, 5]` を返す必要があります。
```js
assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4]), [3, 4, 5]);
```
`sym([1, 2, 3], [5, 2, 1, 4])` には 3 つの要素のみが含まれている必要があります。
```js
assert.equal(sym([1, 2, 3], [5, 2, 1, 4]).length, 3);
```
`sym([1, 2, 3, 3], [5, 2, 1, 4])``[3, 4, 5]` を返す必要があります。
```js
assert.sameMembers(sym([1, 2, 3, 3], [5, 2, 1, 4]), [3, 4, 5]);
```
`sym([1, 2, 3, 3], [5, 2, 1, 4])` には 3 つの要素のみが含まれている必要があります。
```js
assert.equal(sym([1, 2, 3, 3], [5, 2, 1, 4]).length, 3);
```
`sym([1, 2, 3], [5, 2, 1, 4, 5])``[3, 4, 5]` を返す必要があります。
```js
assert.sameMembers(sym([1, 2, 3], [5, 2, 1, 4, 5]), [3, 4, 5]);
```
`sym([1, 2, 3], [5, 2, 1, 4, 5])` には 3 つの要素のみが含まれている必要があります。
```js
assert.equal(sym([1, 2, 3], [5, 2, 1, 4, 5]).length, 3);
```
`sym([1, 2, 5], [2, 3, 5], [3, 4, 5])``[1, 4, 5]` を返す必要があります。
```js
assert.sameMembers(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]), [1, 4, 5]);
```
`sym([1, 2, 5], [2, 3, 5], [3, 4, 5])` には 3 つの要素のみが含まれている必要があります。
```js
assert.equal(sym([1, 2, 5], [2, 3, 5], [3, 4, 5]).length, 3);
```
`sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])``[1, 4, 5]` を返す必要があります。
```js
assert.sameMembers(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]), [1, 4, 5]);
```
`sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5])` には 3 つの要素のみが含まれている必要があります。
```js
assert.equal(sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]).length, 3);
```
`sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])``[2, 3, 4, 6, 7]` を返す必要があります。
```js
assert.sameMembers(
sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]),
[2, 3, 4, 6, 7]
);
```
`sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3])` には 5 つの要素のみが含まれている必要があります。
```js
assert.equal(
sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]).length,
5
);
```
`sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])``[1, 2, 4, 5, 6, 7, 8, 9]` を返す必要があります。
```js
assert.sameMembers(
sym(
[3, 3, 3, 2, 5],
[2, 1, 5, 7],
[3, 4, 6, 6],
[1, 2, 3],
[5, 3, 9, 8],
[1]
),
[1, 2, 4, 5, 6, 7, 8, 9]
);
```
`sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])` には 8 つの要素のみが含まれている必要があります。
```js
assert.equal(
sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3], [5, 3, 9, 8], [1])
.length,
8
);
```
# --seed--
## --seed-contents--
```js
function sym(args) {
return args;
}
sym([1, 2, 3], [5, 2, 1, 4]);
```
# --solutions--
```js
function sym() {
var arrays = [].slice.call(arguments);
return arrays.reduce(function (symDiff, arr) {
return symDiff.concat(arr).filter(function (val, idx, theArr) {
return theArr.indexOf(val) === idx
&& (symDiff.indexOf(val) === -1 || arr.indexOf(val) === -1);
});
});
}
sym([1, 2, 3], [5, 2, 1, 4]);
```

View File

@ -0,0 +1,150 @@
---
id: 61abc7ebf3029b56226de5b6
title: 二分探索を実装する
challengeType: 1
forumTopicId: 487618
dashedName: implement-binary-search
---
# --description--
二分探索はソートされた配列内で要素を検索するアルゴリズムで、その時間計算量は **O(log(n))** です。 次のように演算が行われます。
1. ソートされた配列内の中央の `value` (値) を探します。 `value == target` であれば、「見つけた!」 を返します。
1. 中央の `value < target` であれば、次の比較で配列の右半分を検索します。
1. 中央の `value > target` であれば、次の比較で配列の左半分を検索します。
このように配列を連続的に半減させており、時間計算量は log(n) になります。 このチャレンジでは、あなたがどのような経路をたどって目標値に到達したかを提示していただきます。
# --instructions--
二分探索アルゴリズムを配列に実装し、配列内で目標値を見つけるためにたどった経路 (各回の中間値比較) を返すような関数 `binarySearch` を記述してください。
この関数は、ソートされた整数配列と目標値を入力として取ります。 そして目標値を見つけるまで、元の配列の各 2 分割で見つけた中間値が含まれる配列を返します (通りがけ順)。 目標値は、返される配列の最後の要素でなければなりません。 値が見つからない場合は、文字列 `Value Not Found` (値が見つかりません) を返します。
例えば、`binarySearch([1,2,3,4,5,6,7], 5)``[4,6,5]` を返します。
このチャレンジでは、2 分割する際、除算に `Math.floor()` を必ず使用して `Math.floor(x/2)` としなければなりません。 これにより、一貫性のある検証可能な経路が得られます。
**注:** 検証では以下の配列が使用されます。
```js
const testArray = [
0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 49, 70
];
```
# --hints--
`binarySearch` は関数でなければなりません。
```js
assert(typeof binarySearch == 'function');
```
`binarySearch(testArray, 0)``[13, 5, 2, 0]` を返す必要があります。
```js
assert.deepEqual(binarySearch(_testArray, 0), [13, 5, 2, 0]);
```
`binarySearch(testArray, 1)``[13, 5, 2, 0, 1]` を返す必要があります。
```js
assert.deepEqual(binarySearch(_testArray, 1), [13, 5, 2, 0, 1]);
```
`binarySearch(testArray, 2)``[13, 5, 2]` を返す必要があります。
```js
assert.deepEqual(binarySearch(_testArray, 2), [13, 5, 2]);
```
`binarySearch(testArray, 6)` は文字列 `Value Not Found` を返す必要があります。
```js
assert.strictEqual(binarySearch(_testArray, 6), 'Value Not Found');
```
`binarySearch(testArray, 11)``[13, 5, 10, 11]` を返す必要があります。
```js
assert.deepEqual(binarySearch(_testArray, 11), [13, 5, 10, 11])
```
`binarySearch(testArray, 13)``[13]` を返す必要があります。
```js
assert.deepEqual(binarySearch(_testArray, 13), [13]);
```
# --seed--
## --after-user-code--
```js
const _testArray = [
0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 49, 70
];
```
## --seed-contents--
```js
function binarySearch(searchList, value) {
let arrayPath = [];
return arrayPath;
}
```
# --solutions--
```js
let binarySearch = (searchList, value) => {
let arrayPath = [];
// set initial L - M - R
let left = 0;
let right = searchList.length - 1;
let middle = Math.floor(right / 2);
// if first comparison finds value
if (searchList[middle] == value) {
arrayPath.push(searchList[middle]);
return arrayPath;
}
while (searchList[middle] !== value) {
// add to output array
arrayPath.push(searchList[middle]);
// not found
if (right < left) {
return 'Value Not Found';
}
// value is in left or right portion of array
// update L - M - R
if (searchList[middle] > value) {
right = middle - 1;
middle = left + Math.floor((right - left) / 2);
} else {
left = middle + 1;
middle = left + Math.floor((right - left) / 2);
}
// if found update output array and exit
if (searchList[middle] == value) {
arrayPath.push(searchList[middle]);
break;
}
}
return arrayPath;
};
```

View File

@ -0,0 +1,138 @@
---
id: 8d5123c8c441eddfaeb5bdef
title: バブルソートを実装する
challengeType: 1
forumTopicId: 301612
dashedName: implement-bubble-sort
---
# --description--
このチャレンジは、ソートアルゴリズムに関するいくつかのチャレンジの 1 つ目です。 ソートされていない要素の配列が与えられ、ソートされた配列を返す操作を行います。 これを行うための方法をいくつか知り、それらの異なるアプローチの間にどのようなトレードオフがあるかを学びます。 最近のほとんどの言語にはこのような操作を行うソート方法が組み込まれていますが、一般的な基本アプローチをいくつか理解し、それらの実装方法を学ぶことはやはり重要です。
まずはバブルソートです。 バブルソート法は、ソートされていない配列の先頭から始まり、ソートされていない値を末尾に向けて押し出す「バブルアップ」を行います。これを、配列が完全にソートされるまで繰り返します。 具体的には、隣接する要素を比較し、順序が正しくなければそれらを交換します。 配列がソートされて交換が発生しなくなるまで、この操作が配列内をループし続けます。
この方法では配列全体にわたり操作が何度も繰り返されることになり、平均ケースおよび最悪ケースで二乗時間計算量になります。 単純ですが、ほとんどの状況では一般に実用的ではありません。
**手順:** 整数の配列を入力として受け取り、それらの整数の配列を最小から最大の順にソートして返す、`bubbleSort` 関数を記述してください。
# --hints--
`bubbleSort` は関数でなければなりません。
```js
assert(typeof bubbleSort == 'function');
```
`bubbleSort` はソートされた配列を返す必要があります (最小から最大の順)。
```js
assert(
isSorted(
bubbleSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
])
)
);
```
`bubbleSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])` は、順序以外は変更されていない配列を返す必要があります。
```js
assert.sameMembers(
bubbleSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
]),
[1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]
);
```
`bubbleSort` には組み込みの `.sort()` メソッドを使用しないでください。
```js
assert(isBuiltInSortUsed());
```
# --seed--
## --after-user-code--
```js
function isSorted(a){
for(let i = 0; i < a.length - 1; i++)
if(a[i] > a[i + 1])
return false;
return true;
}
function isBuiltInSortUsed(){
let sortUsed = false;
Array.prototype.sort = () => sortUsed = true;
bubbleSort([0, 1]);
return !sortUsed;
}
```
## --seed-contents--
```js
function bubbleSort(array) {
// Only change code below this line
return array;
// Only change code above this line
}
```
# --solutions--
```js
function bubbleSort(array) {
for (let i = 0; i < array.length; i++) {
let swapped = false;
for (let j = 1; j < array.length; j++) {
if (array[j - 1] > array[j]) {
let temp = array[j-1];
array[j-1] = array[j];
array[j] = temp;
swapped = true;
}
}
if (swapped === false) {
break;
}
}
return array;
}
```

View File

@ -0,0 +1,135 @@
---
id: 587d8259367417b2b2512c86
title: 挿入ソートを実装する
challengeType: 1
forumTopicId: 301613
dashedName: implement-insertion-sort
---
# --description--
次のソート方法は挿入ソートです。 この方法は、ソート済みの配列をリストの先頭に作ることで機能します。 まず、1 つ目の要素を使って、ソート済みの配列を作り始めます。 そして次の要素を調べ、それが正しいソート位置に入るまで、ソート済みの配列の中で後ろの要素と交換していきます。 リスト全体を通してそれを繰り返し、末尾に到達するまで新しい要素を後方に置き換え続けます。 このアルゴリズムは、平均ケースおよび最悪ケースで二乗時間計算量になります。
**手順:** 整数の配列を入力として受け取り、それらの整数の配列を最小から最大の順にソートして返す、`insertionSort` 関数を記述してください。
# --hints--
`insertionSort` は関数でなければなりません。
```js
assert(typeof insertionSort == 'function');
```
`insertionSort` はソートされた配列を返す必要があります (最小から最大の順)。
```js
assert(
isSorted(
insertionSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
])
)
);
```
`insertionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])` は、順序以外は変更されていない配列を返す必要があります。
```js
assert.sameMembers(
insertionSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
]),
[1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]
);
```
`insertionSort([5, 4, 33, 2, 8])``[2, 4, 5, 8, 33]` を返す必要があります。
```js
assert.deepEqual(insertionSort([5, 4, 33, 2, 8]), [2, 4, 5, 8, 33])
```
`insertionSort` には組み込みの `.sort()` メソッドを使用しないでください。
```js
assert(isBuiltInSortUsed());
```
# --seed--
## --after-user-code--
```js
function isSorted(a){
for(let i = 0; i < a.length - 1; i++)
if(a[i] > a[i + 1])
return false;
return true;
}
function isBuiltInSortUsed(){
let sortUsed = false;
Array.prototype.sort = () => sortUsed = true;
insertionSort([0, 1]);
return !sortUsed;
}
```
## --seed-contents--
```js
function insertionSort(array) {
// Only change code below this line
return array;
// Only change code above this line
}
```
# --solutions--
```js
function insertionSort (array) {
for (let currentIndex = 0; currentIndex < array.length; currentIndex++) {
let current = array[currentIndex];
let j = currentIndex - 1;
while (j > -1 && array[j] > current) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = current;
}
return array;
}
```

View File

@ -0,0 +1,156 @@
---
id: 587d825c367417b2b2512c8f
title: マージソートを実装する
challengeType: 1
forumTopicId: 301614
dashedName: implement-merge-sort
---
# --description--
もう一つの一般的な中間ソートアルゴリズムはマージソートです。 クイックソートと同様に、マージソートは再帰的な分割統治法を使用して配列をソートします。 この方法は、最初からそれぞれがソートされている 2 つの配列をソートするのは比較的簡単であるという事実を利用しています。 しかし、まずは入力として配列を 1 つだけ使いましょう。さて、そこから 2 つのソート済み配列をどのように取得するのでしょうか? 要素を 1 つのみ持つ配列という初期条件に到達するまで、元の入力を再帰的に 2 分割すれば良いのです。 単一要素の配列は当然ソート済みなので、次に合体を始めることができます。 この合体により、元の配列を分割する再帰呼び出しが巻き戻され、最後にはすべての要素を持つ最終的なソート済み配列が生成されます。 マージソートの手順は次のとおりです。
**1)** 要素を 1 つのみ持つ部分配列が生成されるまで、入力配列を再帰的に 2 分割します。
**2)** ソート済みの各部分配列をマージして最終的なソート済み配列を生成します。
マージソートは効率的なソート方法で、時間計算量は *O(nlog(n))* です。 このアルゴリズムはパフォーマンスが高く実装が比較的容易であるため、広く使用されます。
余談ですが、これはここで取り扱う最後のソートアルゴリズムです。 ただしツリーデータ構造のセクションの後半で、ヒープソートについて説明します。これも効率的なソート方法であり、その実装には二分ヒープが必要です。
**手順:** 整数の配列を入力として受け取り、それらの整数の配列を最小から最大の順にソートして返す、`mergeSort` 関数を記述してください。 これを実装する良い方法は、1 つの関数、例えば `merge` (ソートされた 2 つの配列をマージする関数) と、別の 1 つの関数、例えば `mergeSort` (merge 関数の入力となる単一要素配列を生成するために再帰的操作を行う関数) を書くことです。 頑張ってください!
# --hints--
`mergeSort` は関数でなければなりません。
```js
assert(typeof mergeSort == 'function');
```
`mergeSort` はソートされた配列を返す必要があります (最小から最大の順)。
```js
assert(
isSorted(
mergeSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
])
)
);
```
`mergeSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])` は、順序以外は変更されていない配列を返す必要があります。
```js
assert.sameMembers(
mergeSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
]),
[1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]
);
```
`mergeSort` には組み込みの `.sort()` メソッドを使用しないでください。
```js
assert(isBuiltInSortUsed());
```
# --seed--
## --after-user-code--
```js
function isSorted(a){
for(let i = 0; i < a.length - 1; i++)
if(a[i] > a[i + 1])
return false;
return true;
}
function isBuiltInSortUsed(){
let sortUsed = false;
Array.prototype.sort = () => sortUsed = true;
mergeSort([0, 1]);
return !sortUsed;
}
```
## --seed-contents--
```js
function mergeSort(array) {
// Only change code below this line
return array;
// Only change code above this line
}
```
# --solutions--
```js
function mergeSort(array) {
if (array.length === 1) {
return array;
} else {
const splitIndex = Math.floor(array.length / 2);
return merge(
mergeSort(array.slice(0, splitIndex)),
mergeSort(array.slice(splitIndex))
);
}
// Merge two sorted arrays
function merge(array1, array2) {
let merged = [];
while (array1.length && array2.length) {
if (array1[0] < array2[0]) {
merged.push(array1.shift());
} else if (array1[0] > array2[0]) {
merged.push(array2.shift());
} else {
merged.push(array1.shift(), array2.shift());
}
}
// After looping ends, one array is empty, and other array contains only
// values greater than all values in `merged`
return [...merged, ...array1, ...array2];
}
}
mergeSort([1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]);
```

View File

@ -0,0 +1,142 @@
---
id: 587d825a367417b2b2512c89
title: クイックソートを実装する
challengeType: 1
forumTopicId: 301615
dashedName: implement-quick-sort
---
# --description--
次は、中間ソートアルゴリズムであるクイックソートです。 クイックソートは、配列を効率的にソートするための再帰的な分割統治法です。 この方法では、元の配列でピボット値が選択されます。 次に、配列は、ピボット値よりも小さい値と大きい値の 2 つの部分配列に分割されます。 次に、両方の部分配列でクイックソートアルゴリズムを再帰的に呼び出した結果を組み合わせます。 これは、空の配列または単一要素の配列という初期条件に達するまで続き、私たちはそれを返します。 再帰呼び出しを巻き戻すと、ソートされた配列が返されます。
クイックソートは非常に効率的なソート方法で、平均で *O(nlog(n))* のパフォーマンスを提供します。 また、実装も比較的容易です。 これらの特性を持つため、クイックソートはよく使用される便利なソート方法です。
**手順:** 整数の配列を入力として受け取り、それらの整数の配列を最小から最大の順にソートして返す、`quickSort` 関数を記述してください。 ピボット値の選択は重要ですが、ここでの目的上、どのようなピボットでも構いません。 単純化するために、最初または最後の要素を使用することもできます。
# --hints--
`quickSort` は関数でなければなりません。
```js
assert(typeof quickSort == 'function');
```
`quickSort` はソートされた配列を返す必要があります (最小から最大の順)。
```js
assert(
isSorted(
quickSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
])
)
);
```
`quickSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])` は、順序以外は変更されていない配列を返す必要があります。
```js
assert.sameMembers(
quickSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
]),
[1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]
);
```
`quickSort` には組み込みの `.sort()` メソッドを使用しないでください。
```js
assert(isBuiltInSortUsed());
```
# --seed--
## --after-user-code--
```js
function isSorted(a){
for(let i = 0; i < a.length - 1; i++)
if(a[i] > a[i + 1])
return false;
return true;
}
function isBuiltInSortUsed(){
let sortUsed = false;
Array.prototype.sort = () => sortUsed = true;
quickSort([0, 1]);
return !sortUsed;
}
```
## --seed-contents--
```js
function quickSort(array) {
// Only change code below this line
return array;
// Only change code above this line
}
```
# --solutions--
```js
function quickSort(array) {
if (array.length === 0) {
return [];
} else {
const pivotValue = array[0];
// Sort elements into three piles
let lesser = [];
let equal = [];
let greater = [];
for (let e of array) {
if (e < pivotValue) {
lesser.push(e);
} else if (e > pivotValue) {
greater.push(e);
} else {
equal.push(e);
}
}
return [...quickSort(lesser), ...equal, ...quickSort(greater)];
}
}
```

View File

@ -0,0 +1,131 @@
---
id: 587d8259367417b2b2512c85
title: 選択ソートを実装する
challengeType: 1
forumTopicId: 301616
dashedName: implement-selection-sort
---
# --description--
ここでは選択ソートを実装します。 選択ソートは、まずリスト内の最小値を選択し、それをリスト内の最初の値と交換します。 次に、2 番目の位置から始め、残りのリスト内の最小値を選択し、2 番目の要素と交換します。 リストの最後に到達するまで、リスト全体で要素の入れ替えを繰り返します。 これで、リストがソートされます。 選択ソートは、どのケースでも二乗時間計算量です。
**手順**: 整数の配列を入力として受け取り、それらの整数の配列を最小から最大の順にソートして返す、`selectionSort` 関数を記述してください。
# --hints--
`selectionSort` は関数でなければなりません。
```js
assert(typeof selectionSort == 'function');
```
`selectionSort` はソートされた配列を返す必要があります (最小から最大の順)。
```js
assert(
isSorted(
selectionSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
])
)
);
```
`selectionSort([1,4,2,8,345,123,43,32,5643,63,123,43,2,55,1,234,92])` は、順序以外は変更されていない配列を返す必要があります。
```js
assert.sameMembers(
selectionSort([
1,
4,
2,
8,
345,
123,
43,
32,
5643,
63,
123,
43,
2,
55,
1,
234,
92
]),
[1, 4, 2, 8, 345, 123, 43, 32, 5643, 63, 123, 43, 2, 55, 1, 234, 92]
);
```
`selectionSort` には組み込みの `.sort()` メソッドを使用しないでください。
```js
assert(isBuiltInSortUsed());
```
# --seed--
## --after-user-code--
```js
function isSorted(a){
for(let i = 0; i < a.length - 1; i++)
if(a[i] > a[i + 1])
return false;
return true;
}
function isBuiltInSortUsed(){
let sortUsed = false;
Array.prototype.sort = () => sortUsed = true;
selectionSort([0, 1]);
return !sortUsed;
}
```
## --seed-contents--
```js
function selectionSort(array) {
// Only change code below this line
return array;
// Only change code above this line
}
```
# --solutions--
```js
function selectionSort(array) {
for (let i = 0; i < array.length-1; i++) {
let minimumIndex = i;
for (let j = i+1; j < array.length; j++){
if (array[j] < array[minimumIndex]) {
minimumIndex = j;
}
}
let value = array[minimumIndex];
array[minimumIndex] = array[i];
array[i] = value;
}
return array;
}
```

View File

@ -0,0 +1,228 @@
---
id: a56138aff60341a09ed6c480
title: 在庫を更新する
challengeType: 5
forumTopicId: 16019
dashedName: inventory-update
---
# --description--
二次元配列に格納されている在庫を、フレッシュデリバリーの 2 つ目の二次元配列と比較して更新します。 既存の在庫品目の数量 (`arr1` 内) を更新します。 品目が見つからない場合は、新しい品目と数量を在庫配列に追加します。 返された在庫配列は、品目名でアルファベット順にする必要があります。
# --hints--
関数 `updateInventory` は配列を返す必要があります。
```js
assert.isArray(
updateInventory(
[
[21, 'Bowling Ball'],
[2, 'Dirty Sock'],
[1, 'Hair Pin'],
[5, 'Microphone']
],
[
[2, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[67, 'Bowling Ball'],
[7, 'Toothpaste']
]
)
);
```
`updateInventory([[21, "Bowling Ball"], [2, "Dirty Sock"], [1, "Hair Pin"], [5, "Microphone"]], [[2, "Hair Pin"], [3, "Half-Eaten Apple"], [67, "Bowling Ball"], [7, "Toothpaste"]])` は長さ 6 の配列を返す必要があります。
```js
assert.equal(
updateInventory(
[
[21, 'Bowling Ball'],
[2, 'Dirty Sock'],
[1, 'Hair Pin'],
[5, 'Microphone']
],
[
[2, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[67, 'Bowling Ball'],
[7, 'Toothpaste']
]
).length,
6
);
```
`updateInventory([[21, "Bowling Ball"], [2, "Dirty Sock"], [1, "Hair Pin"], [5, "Microphone"]], [[2, "Hair Pin"], [3, "Half-Eaten Apple"], [67, "Bowling Ball"], [7, "Toothpaste"]])``[[88, "Bowling Ball"], [2, "Dirty Sock"], [3, "Hair Pin"], [3, "Half-Eaten Apple"], [5, "Microphone"], [7, "Toothpaste"]]` を返す必要があります。
```js
assert.deepEqual(
updateInventory(
[
[21, 'Bowling Ball'],
[2, 'Dirty Sock'],
[1, 'Hair Pin'],
[5, 'Microphone']
],
[
[2, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[67, 'Bowling Ball'],
[7, 'Toothpaste']
]
),
[
[88, 'Bowling Ball'],
[2, 'Dirty Sock'],
[3, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[5, 'Microphone'],
[7, 'Toothpaste']
]
);
```
`updateInventory([[21, "Bowling Ball"], [2, "Dirty Sock"], [1, "Hair Pin"], [5, "Microphone"]], [])``[[21, "Bowling Ball"], [2, "Dirty Sock"], [1, "Hair Pin"], [5, "Microphone"]]` を返す必要があります。
```js
assert.deepEqual(
updateInventory(
[
[21, 'Bowling Ball'],
[2, 'Dirty Sock'],
[1, 'Hair Pin'],
[5, 'Microphone']
],
[]
),
[
[21, 'Bowling Ball'],
[2, 'Dirty Sock'],
[1, 'Hair Pin'],
[5, 'Microphone']
]
);
```
`updateInventory([], [[2, "Hair Pin"], [3, "Half-Eaten Apple"], [67, "Bowling Ball"], [7, "Toothpaste"]])``[[67, "Bowling Ball"], [2, "Hair Pin"], [3, "Half-Eaten Apple"], [7, "Toothpaste"]]` を返す必要があります。
```js
assert.deepEqual(
updateInventory(
[],
[
[2, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[67, 'Bowling Ball'],
[7, 'Toothpaste']
]
),
[
[67, 'Bowling Ball'],
[2, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[7, 'Toothpaste']
]
);
```
`updateInventory([[0, "Bowling Ball"], [0, "Dirty Sock"], [0, "Hair Pin"], [0, "Microphone"]], [[1, "Hair Pin"], [1, "Half-Eaten Apple"], [1, "Bowling Ball"], [1, "Toothpaste"]])``[[1, "Bowling Ball"], [0, "Dirty Sock"], [1, "Hair Pin"], [1, "Half-Eaten Apple"], [0, "Microphone"], [1, "Toothpaste"]]` を返す必要があります。
```js
assert.deepEqual(
updateInventory(
[
[0, 'Bowling Ball'],
[0, 'Dirty Sock'],
[0, 'Hair Pin'],
[0, 'Microphone']
],
[
[1, 'Hair Pin'],
[1, 'Half-Eaten Apple'],
[1, 'Bowling Ball'],
[1, 'Toothpaste']
]
),
[
[1, 'Bowling Ball'],
[0, 'Dirty Sock'],
[1, 'Hair Pin'],
[1, 'Half-Eaten Apple'],
[0, 'Microphone'],
[1, 'Toothpaste']
]
);
```
# --seed--
## --seed-contents--
```js
function updateInventory(arr1, arr2) {
return arr1;
}
// Example inventory lists
var curInv = [
[21, "Bowling Ball"],
[2, "Dirty Sock"],
[1, "Hair Pin"],
[5, "Microphone"]
];
var newInv = [
[2, "Hair Pin"],
[3, "Half-Eaten Apple"],
[67, "Bowling Ball"],
[7, "Toothpaste"]
];
updateInventory(curInv, newInv);
```
# --solutions--
```js
function updateInventory(arr1, arr2) {
arr2.forEach(function(item) {
createOrUpdate(arr1, item);
});
// All inventory must be accounted for or you're fired!
return arr1;
}
function createOrUpdate(arr1, item) {
var index = -1;
while (++index < arr1.length) {
if (arr1[index][1] === item[1]) {
arr1[index][0] += item[0];
return;
}
if (arr1[index][1] > item[1]) {
break;
}
}
arr1.splice(index, 0, item);
}
// Example inventory lists
var curInv = [
[21, 'Bowling Ball'],
[2, 'Dirty Sock'],
[1, 'Hair Pin'],
[5, 'Microphone']
];
var newInv = [
[2, 'Hair Pin'],
[3, 'Half-Eaten Apple'],
[67, 'Bowling Ball'],
[7, 'Toothpaste']
];
updateInventory(curInv, newInv);
```

View File

@ -0,0 +1,126 @@
---
id: a7bf700cd123b9a54eef01d5
title: 繰り返しなし
challengeType: 5
forumTopicId: 16037
dashedName: no-repeats-please
---
# --description--
与えられた文字列の全順列のうち、同じ文字の連続的な繰り返しを含まない順列がいくつあるかを返します。 与えられた文字列のすべての文字がそれぞれ一意であると仮定します。
例えば `aab` は、計 6 つの順列 (`aab`, `aab`, `aba`, `aba`, `baa`, `baa`) を持ちますが、そのうち 2 つ (`aba``aba`) だけは同じ文字 (この場合は `a`) が繰り返されていないので、2 を返す必要があります。
# --hints--
`permAlone("aab")` は数値を返す必要があります。
```js
assert.isNumber(permAlone('aab'));
```
`permAlone("aab")` は 2 を返す必要があります。
```js
assert.strictEqual(permAlone('aab'), 2);
```
`permAlone("aaa")` は 0 を返す必要があります。
```js
assert.strictEqual(permAlone('aaa'), 0);
```
`permAlone("aabb")` は 8 を返す必要があります。
```js
assert.strictEqual(permAlone('aabb'), 8);
```
`permAlone("abcdefa")` は 3600 を返す必要があります。
```js
assert.strictEqual(permAlone('abcdefa'), 3600);
```
`permAlone("abfdefa")` は 2640 を返す必要があります。
```js
assert.strictEqual(permAlone('abfdefa'), 2640);
```
`permAlone("zzzzzzzz")` は 0 を返す必要があります。
```js
assert.strictEqual(permAlone('zzzzzzzz'), 0);
```
`permAlone("a")` は 1 を返す必要があります。
```js
assert.strictEqual(permAlone('a'), 1);
```
`permAlone("aaab")` は 0 を返す必要があります。
```js
assert.strictEqual(permAlone('aaab'), 0);
```
`permAlone("aaabb")` は 12 を返す必要があります。
```js
assert.strictEqual(permAlone('aaabb'), 12);
```
# --seed--
## --seed-contents--
```js
function permAlone(str) {
return str;
}
permAlone('aab');
```
# --solutions--
```js
function permAlone(str) {
return permuter(str).filter(function(perm) {
return !perm.match(/(.)\1/g);
}).length;
}
function permuter(str) {
// http://staff.roguecc.edu/JMiller/JavaScript/permute.html
//permArr: Global array which holds the list of permutations
//usedChars: Global utility array which holds a list of "currently-in-use" characters
var permArr = [], usedChars = [];
function permute(input) {
//convert input into a char array (one element for each character)
var i, ch, chars = input.split("");
for (i = 0; i < chars.length; i++) {
//get and remove character at index "i" from char array
ch = chars.splice(i, 1);
//add removed character to the end of used characters
usedChars.push(ch);
//when there are no more characters left in char array to add, add used chars to list of permutations
if (chars.length === 0) permArr[permArr.length] = usedChars.join("");
//send characters (minus the removed one from above) from char array to be permuted
permute(chars.join(""));
//add removed character back into char array in original position
chars.splice(i, 0, ch);
//remove the last character used off the end of used characters array
usedChars.pop();
}
}
permute(str);
return permArr;
}
permAlone('aab');
```

View File

@ -0,0 +1,100 @@
---
id: a3f503de51cfab748ff001aa
title: ペアワイズ
challengeType: 5
forumTopicId: 301617
dashedName: pairwise
---
# --description--
配列 `arr` について、和が 2 つ目の引数 `arg` に等しくなる要素ペアを見つけ、それらのインデックスの和を返します。
数値要素は同じだがインデックスが異なる、複数のペアを使用できます。 各ペアは、利用可能な最低のインデックスを使用する必要があります。 一度要素を使用すると、それを他の要素とペアリングすることはできません。 例えば、`pairwise([1, 1, 2], 3)`は、インデックス 1 にある 1 ではなく、インデックス 0 にある 1 を使って、ペア `[2, 1]` を作成します。なぜなら、0+2 &lt; 1+2 だからです。
例えば、`pairwise([7, 9, 11, 13, 15], 20)``6` を返します。 和が 20 であるペアは `[7, 13]``[9, 11]` です。 次に、それらのインデックスと値を使って配列を書き出すことができます。
<div style='margin-left: 2em;'>
| インデックス | 0 | 1 | 2 | 3 | 4 |
| ----- | - | - | -- | -- | -- |
| 値 | 7 | 9 | 11 | 13 | 15 |
</div>
以下では、対応するインデックスを取り、追加します。
<div style='margin-left: 2em;'>
7 + 13 = 20 → インデックス 0 + 3 = 3
9 + 11 = 20 → インデックス 1 + 2 = 3
3 + 3 = 6 → `6` を返す
</div>
# --hints--
`pairwise([1, 4, 2, 3, 0, 5], 7)` は 11 を返す必要があります。
```js
assert.deepEqual(pairwise([1, 4, 2, 3, 0, 5], 7), 11);
```
`pairwise([1, 3, 2, 4], 4)` は 1 を返す必要があります。
```js
assert.deepEqual(pairwise([1, 3, 2, 4], 4), 1);
```
`pairwise([1, 1, 1], 2)` は 1 を返す必要があります。
```js
assert.deepEqual(pairwise([1, 1, 1], 2), 1);
```
`pairwise([0, 0, 0, 0, 1, 1], 1)` は 10 を返す必要があります。
```js
assert.deepEqual(pairwise([0, 0, 0, 0, 1, 1], 1), 10);
```
`pairwise([], 100)` は 0 を返す必要があります。
```js
assert.deepEqual(pairwise([], 100), 0);
```
# --seed--
## --seed-contents--
```js
function pairwise(arr, arg) {
return arg;
}
pairwise([1,4,2,3,0,5], 7);
```
# --solutions--
```js
function pairwise(arr, arg) {
var sum = 0;
arr.forEach(function(e, i, a) {
if (e != null) {
var diff = arg-e;
a[i] = null;
var dix = a.indexOf(diff);
if (dix !== -1) {
sum += dix;
sum += i;
a[dix] = null;
}
}
});
return sum;
}
pairwise([1,4,2,3,0,5], 7);
```

View File

@ -0,0 +1,191 @@
---
id: 587d8257367417b2b2512c7b
title: 二分探索木に新しい要素を追加する
challengeType: 1
forumTopicId: 301618
dashedName: add-a-new-element-to-a-binary-search-tree
---
# --description--
この一連のチャレンジでは、ツリーデータ構造について学びます。 木 (ツリー) は、コンピュータサイエンスにおいて重要かつ汎用的なデータ構造です。 もちろん名称の由来は、そのデータ構造を視覚化すると自然界の木に似ていることです。 ツリーデータ構造は、一般に「根」と呼ばれる 1 つのノードで始まり、ここから追加のノードに枝分かれします。それぞれのノードがいくつかの子ノードに枝分かれし、その子ノードがさらに枝分かれしていきます。 データ構造を視覚化する際、通常は根ノードを一番上に置くので、木を逆さにした状態と考えることができます。
最初に、木に関してよく使われる用語について説明します。 「根ノード」は木の一番上にあります。 木の中のデータポイントは「ノード」と呼ばれます。 他のノードにつながる枝を持つノードは、枝の先にあるノード (子) の親と呼ばれます。 他に複雑な関連用語がありますが、それぞれ言葉通りの意味です。 「部分木」は特定ノードのすべての子孫を指し、枝は「エッジ」と呼ばれることもあります。「葉ノード」は、子を持たず木の末端にあるノードです。 最後に、木は本質的に再帰的なデータ構造であることに注目してください。 つまり、あるノードの子はそれが持つ部分木の親でもあり、それが子孫で繰り返されていきます。 木に対する一般的な操作のアルゴリズムを設計する際には、木の再帰性を理解することが重要です。
最初に、特別な種類の木 (二分木) について説明します。 実際には、特別な二分木である「二分探索木」についてです。 これが何を意味するのかを以下に説明します。 ツリーデータ構造では 1 つの ノードが何本でも枝を持てますが、二分木ではすべてのノードに枝が 2 本しかありません。 さらに二分探索木では、左部分木の各ノードの値が親ノードの値以下になり、右部分木の各ノードの値が親ノードの値以上になるという形で、子部分木を基準にして順序が決まります。 視覚化すると、この関係は一目瞭然です。
<div style='width: 100%; display: flex; justify-content: center; align-items: center;'><img style='width: 100%; max-width: 350px; background-color: var(--gray-05);' src='https://user-images.githubusercontent.com/18563015/32136009-1e665d98-bbd6-11e7-9133-63184f9f9182.png'></div>
これで、順序付けの関係が簡単に分かります。 注目すべき点は、根ノードである 8 の左側の値はすべて 8 より小さく、右側の値はすべて 8 より大きいということです。 また、この関係がそれぞれの部分木にも当てはまるという点に注意してください。 例えば、左側にある最初の子は部分木です。 3 は親ノードであり、ちょうど 2 つの子ノードを持っています。二分探索木のルールにより、このノードの左側の子 (およびそのすべての子) は 3 より小さく、右側の子 (およびそのすべての子) は 3 よりも大きい (ただし、この構造の根の値よりも小さい) ということは、もう見なくても分かります。
二分探索木は、検索、挿入、削除などの一般的な操作の平均ケースで対数時間計算量なので、非常によく使われる便利なデータ構造です。
# --instructions--
シンプルなもので始めましょう。 ここでは、木のノードを作成する関数に加えて、二分探索木構造のスケルトンを定義してあります。 各ノードの左右に値があることを確認してください (ない場合もあります)。 それらには子部分木が割り当てられます (それらが存在する場合)。 ここで、この二分探索木に新しい値を追加するメソッドを作成してください。 そのメソッドは `add` と呼ばれ、木に追加する整数値を受け入れる必要があります。 二分探索木の不変条件を必ず守ってください。つまり、左側のそれぞれの子の値は親値以下、右側のそれぞれ子の値は親値以上でなければなりません。 ここでは、ツリーが重複値を保持できないようにしましょう。 既に存在する値を追加しようとした場合、メソッドから `null` が返される必要があります。 それ以外の場合、追加が成功したら `undefined` が返される必要があります。
**ヒント:** 木は本質的に再帰的なデータ構造です!
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `add` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.add == 'function';
})()
);
```
add メソッドは二分探索木のルールに従って要素を追加する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.add !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
const expectedResult = [1, 4, 7, 8, 34, 45, 73, 87];
const result = test.inOrder();
return expectedResult.toString() === result.toString();
})()
);
```
既に存在する要素を追加すると、`null` が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.add !== 'function') {
return false;
}
test.add(4);
return test.add(4) == null;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
inOrder() {
if (!this.root) {
return null;
}
var result = new Array();
function traverseInOrder(node) {
node.left && traverseInOrder(node.left);
result.push(node.value);
node.right && traverseInOrder(node.right);
}
traverseInOrder(this.root);
return result;
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.add = function(element) {
let current = this.root;
if (!current) {
this.root = new Node(element);
return;
} else {
const searchTree = function(current) {
if (current.value > element) {
if (current.left) {
return searchTree(current.left);
} else {
current.left = new Node(element);
return;
}
} else if (current.value < element) {
if (current.right) {
return searchTree(current.right);
} else {
current.right = new Node(element);
return;
}
} else {
return null;
}
};
return searchTree(current);
}
};
}
```

View File

@ -0,0 +1,161 @@
---
id: 587d8252367417b2b2512c67
title: リンクリストの特定のインデックスに要素を追加する
challengeType: 1
forumTopicId: 301619
dashedName: add-elements-at-a-specific-index-in-a-linked-list
---
# --description--
与えられたインデックスの位置に要素を追加する addAt(index,element) メソッドを作成しましょう。 与えられたインデックスの位置にある要素を削除する方法と同様に、リンクリストを走査する際に currentIndex を追跡する必要があります。 currentIndex と与えられたインデックスとが一致する場合、前のノードの next プロパティを再び割り当て、追加された新しいノードを参照する必要があります。 新しいードは、currentIndex 内の次のノードを参照する必要があります。 コンガラインの例に戻りましょう。新しい人がラインの途中に加わりたいと考えています。 あなたは列の途中にいるので、自分の手を前の人から離します。 新しい人が歩いてきて、今まであなたが手を置いていた人に手を置きます。そしてあなたは新しい人に手を置きます。
# --instructions--
与えられたインデックスの位置に要素を追加する `addAt(index,element)` メソッドを作成してください。 要素を追加できなかった場合は false を返してください。 **注:** 与えられたインデックスが負であるか、リンクリストの長さよりも長いかを必ず調べてください。
# --hints--
与えられたインデックスが 0 の場合、`addAt` メソッドは `head` を新しいノードに再割り当てする必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.addAt(0, 'fish');
return test.head().element === 'fish' && test.head().next.element === 'cat';
})()
);
```
`addAt` メソッドは、リンクリストに新しいノードが追加されるたびに、リンクリストの長さを 1 ずつ増やす必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.addAt(0, 'cat');
return test.size() === 3;
})()
);
```
`addAt` メソッドは、ノードを追加できなかった場合に `false` を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
return test.addAt(4, 'cat') === false;
})()
);
```
# --seed--
## --seed-contents--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element) {
this.element = element;
this.next = null;
};
this.size = function() {
return length;
};
this.head = function() {
return head;
};
this.add = function(element) {
var node = new Node(element);
if (head === null) {
head = node;
} else {
var currentNode = head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.size = function(){
return length;
};
this.head = function(){
return head;
};
this.add = function(element){
var node = new Node(element);
if (head === null){
head = node;
} else {
var currentNode = head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
this.addAt = function (index, element) {
if (index > length || index < 0) {
return false;
}
var newNode = new Node(element);
var currentNode = head;
if (index === 0) {
head = newNode;
} else {
var previousNode = null;
var i = 0;
while (currentNode && i < index) {
previousNode = currentNode;
currentNode = currentNode.next;
i++;
}
previousNode.next = newNode;
}
newNode.next = currentNode;
length++;
}
}
```

View File

@ -0,0 +1,91 @@
---
id: 587d8256367417b2b2512c77
title: 隣接リスト
challengeType: 1
forumTopicId: 301620
dashedName: adjacency-list
---
# --description--
グラフはさまざまな方法で表すことができます。 ここでは、<dfn>隣接リスト</dfn>と呼ばれる方法について説明します。 隣接リストは基本的に箇条書きリストで、左側がノードであり、右側にはそのノードが接続されている他のすべてのノードが列挙されます。 隣接リストの表現を次に示します。
<blockquote>Node1: Node2, Node3<br>Node2: Node1<br>Node3: Node1</blockquote>
上のリストでは、`Node1``Node2``Node3` に接続されており、その情報は `Node2``Node3` が示す接続と一致しているので、無向グラフです。 有向グラフの隣接リストとは、リストの各行が方向を示しているリストのことです。 これが有向グラフであった場合、`Node2: Node1` とは、そこでは有向エッジ (枝) が `Node2` から `Node1` へ向かっているという意味です。 JavaScript オブジェクトの中に入れることで、上の無向グラフを隣接リストとして表すことができます。
```js
var undirectedG = {
Node1: ["Node2", "Node3"],
Node2: ["Node1"],
Node3: ["Node1"]
};
```
これは、ノードが文字列ラベルではなく数字だけを持つ配列として、より単純に表現することもできます。
```js
var undirectedGArr = [
[1, 2], // Node1
[0], // Node2
[0] // Node3
];
```
# --instructions--
`James``Jill``Jenny``Jeff` という 4 つ (4人) のノードを持つ無向グラフとしてソーシャルネットワークを作成してください。 James と Jeff の間、Jill と Jenny の間、および Jeff と Jenny の間にはエッジ / 関係があります。
# --hints--
`undirected AdjList` には 4 つのノードのみが含まれている必要があります。
```js
assert(Object.keys(undirectedAdjList).length === 4);
```
`Jeff``James` の間にはエッジが必要です。
```js
assert(
undirectedAdjList.James.indexOf('Jeff') !== -1 &&
undirectedAdjList.Jeff.indexOf('James') !== -1
);
```
`Jill``Jenny` の間にはエッジが必要です。
```js
assert(
undirectedAdjList.Jill.indexOf('Jenny') !== -1 &&
undirectedAdjList.Jenny.indexOf('Jill') !== -1
);
```
`Jeff``Jenny` の間にはエッジが必要です。
```js
assert(
undirectedAdjList.Jeff.indexOf('Jenny') !== -1 &&
undirectedAdjList.Jenny.indexOf('Jeff') !== -1
);
```
# --seed--
## --seed-contents--
```js
var undirectedAdjList = {};
```
# --solutions--
```js
var undirectedAdjList = {
James: ['Jeff'],
Jill: ['Jenny'],
Jenny: ['Jill', 'Jeff'],
Jeff: ['James', 'Jenny']
};
```

View File

@ -0,0 +1,108 @@
---
id: 587d8256367417b2b2512c78
title: 隣接行列
challengeType: 1
forumTopicId: 301621
dashedName: adjacency-matrix
---
# --description--
グラフを表すもう一つの方法は、<dfn>隣接行列</dfn>に入れることです。 <dfn>隣接行列</dfn>は二次元 (2D) 配列で、入れ子になった各配列は外側の配列と同じ数の要素を持っています。 言い換えれば、数字の行列または格子であり、数字はエッジ (枝) を表します。
**注**: 行列の上と左の数字は、ノードの単なるラベルです。 行列内の 1 は、行と列を表す頂点 (ノード) の間にエッジが存在することを意味します。 最後に、0 はエッジ (関係) がないことを意味します。
<pre>
1 2 3
\------
1 | 0 1 1
2 | 1 0 0
3 | 1 0 0
</pre>
上記は非常にシンプルな無向グラフで、3 つのノードがあり、最初のノードが 2 番目と 3 番目のノードに接続されています。 下記は、同じことを JavaScript で実装したものです。
```js
var adjMat = [
[0, 1, 1],
[1, 0, 0],
[1, 0, 0]
];
```
隣接リストとは異なり、行列の各「行」は、グラフ内のノードと同じ数の要素を持たなければなりません。 これは 3 × 3 の行列であり、つまりグラフに 3 つのノードがあります。 有向グラフもこれに似ています。 下のグラフでは、最初のノードは 2 番目のードに向かうエッジを持ち、2 番目のノードは 3 番目のノードに向かうエッジを持っています。
```js
var adjMatDirected = [
[0, 1, 0],
[0, 0, 1],
[0, 0, 0]
];
```
グラフのエッジに<dfn>重み</dfn>を付けることもできます。 これまでに見てきたエッジは、単にエッジの有無が二項 (`0` または `1`) で表された、<dfn>重み付けされていない</dfn>エッジです。 用途によって重みを変えることができます。
# --instructions--
5 つのノードを持つ無向グラフの隣接行列を作成してください。 この行列は多次元配列でなければなりません。 これら 5 つのードは、1 番目と 4 番目のード、1 番目と 3 番目のード、3 番目と 5 番目のノード、および 4 番目と 5 番目のノードの間に関係があります。 エッジの重みはすべて 1 です。
# --hints--
`undirectedAdjList` には 5 つのノードのみが含まれている必要があります。
```js
assert(
adjMatUndirected.length === 5 &&
adjMatUndirected
.map(function (x) {
return x.length === 5;
})
.reduce(function (a, b) {
return a && b;
})
);
```
1 番目と 4 番目のノードの間にはエッジが必要です。
```js
assert(adjMatUndirected[0][3] === 1 && adjMatUndirected[3][0] === 1);
```
1 番目と 3 番目のノードの間にはエッジが必要です。
```js
assert(adjMatUndirected[0][2] === 1 && adjMatUndirected[2][0] === 1);
```
3 番目と 5 番目のノードの間にはエッジが必要です。
```js
assert(adjMatUndirected[2][4] === 1 && adjMatUndirected[4][2] === 1);
```
There should be an edge between the fourth and fifth node.
```js
assert(adjMatUndirected[3][4] === 1 && adjMatUndirected[4][3] === 1);
```
# --seed--
## --seed-contents--
```js
var adjMatUndirected = [];
```
# --solutions--
```js
var adjMatUndirected = [
[0, 0, 1, 1, 0],
[0, 0, 0, 0, 0],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[0, 0, 1, 1, 0]
];
```

View File

@ -0,0 +1,182 @@
---
id: 587d825c367417b2b2512c90
title: 幅優先探索
challengeType: 1
forumTopicId: 301622
dashedName: breadth-first-search
---
# --description--
これまで、グラフを表現するさまざまな方法を学びました。 次は何でしょう? 自然に生まれる問いは、グラフ内の 2 つのノード間の距離はどのくらいかということです。 そこで、<dfn>グラフ走査アルゴリズム</dfn>の出番です。
<dfn>走査アルゴリズム</dfn>は、グラフ内のノードを走査したり訪問したりするためのアルゴリズムです。 走査アルゴリズムのタイプの一つは、幅優先探索アルゴリズムです。
このアルゴリズムは 1 つのノードから始まり、エッジ 1 本分だけ離れているすべての隣接ノードを訪問します。 その後、すべてのノードに到達するまで、それぞれの隣接ノードを訪れ続けます。
幅優先探索アルゴリズムを実装するのに役立つ重要なデータ構造は、キューです。 これは、一方の端に要素を追加し、もう一方の端から要素を削除することができる配列です。 これは、<dfn>FIFO</dfn> または<dfn>先入れ先出し</dfn>のデータ構造とも呼ばれます。
このアルゴリズムが行っていることを視覚的に表すと、このようになります。 ![木の中を移動する幅優先探索アルゴリズム](https://camo.githubusercontent.com/2f57e6239884a1a03402912f13c49555dec76d06/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f342f34362f416e696d617465645f4246532e676966)
灰色はキューに追加されるノードを表し、黒はキューから削除されるノードを表します。 ノードがキューから削除される (ノードが黒に変わる) たびに、すべての隣接ノードがキューに追加される (ノードが灰色に変わる) 様子を確認してください。
このアルゴリズムを実装するには、グラフ構造と開始ノードを入力する必要があります。
まず、開始ノードからの距離、すなわち開始ノードからのエッジの数を知る必要があります。 `Infinity` のような大きな数字ですべての距離を開始します。 これにより、開始ノードから到達できないノードがある場合のカウントの問題を防ぎます。 次に、開始ノードから隣接ノードに移動します。 これらの隣接ノードはエッジ 1 本分だけ離れており、この時点で、あなたが追跡している距離に 1 単位の距離を追加する必要があります。
# --instructions--
隣接行列グラフ (二次元配列) とノードラベルの根 (開始ノード) をパラメータとして取る関数、`bfs()` を記述してください。 ノードラベルは単に `0` から `n - 1` の間の整数値です (`n` はグラフ内のノードの総数)。
Your function will output a JavaScript object key-value pairs with the node and its distance from the root. そのノードに到達できなかった場合、そのノードは `Infinity` の距離を持つ必要があります。
# --hints--
`1` の開始ノードを持つ入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` は、`{0: 1, 1: 0, 2: 1, 3: 2}` を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
var results = bfs(graph, 1);
return isEquivalent(results, { 0: 1, 1: 0, 2: 1, 3: 2 });
})()
);
```
`1` の開始ノードを持つ入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` は、`{0: 1, 1: 0, 2: 1, 3: Infinity}` を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
var results = bfs(graph, 1);
return isEquivalent(results, { 0: 1, 1: 0, 2: 1, 3: Infinity });
})()
);
```
`0` の開始ノードを持つ入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` は、`{0: 0, 1: 1, 2: 2, 3: 3}` を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
var results = bfs(graph, 0);
return isEquivalent(results, { 0: 0, 1: 1, 2: 2, 3: 3 });
})()
);
```
入力グラフ `[[0, 1], [1, 0]]` の開始ノードが `0` の場合、`{0: 0, 1: 1}` を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1],
[1, 0]
];
var results = bfs(graph, 0);
return isEquivalent(results, { 0: 0, 1: 1 });
})()
);
```
# --seed--
## --after-user-code--
```js
// Source: http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html
function isEquivalent(a, b) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
// If values of same property are not equal,
// objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
```
## --seed-contents--
```js
function bfs(graph, root) {
var nodesLen = {};
return nodesLen;
};
var exBFSGraph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
console.log(bfs(exBFSGraph, 3));
```
# --solutions--
```js
function bfs(graph, root) {
var nodesLen = {};
// Set all distances to infinity
for (var i = 0; i < graph.length; i++) {
nodesLen[i] = Infinity;
}
nodesLen[root] = 0; // ...except root node
var queue = [root]; // Keep track of nodes to visit
var current; // Current node traversing
// Keep on going until no more nodes to traverse
while (queue.length !== 0) {
current = queue.shift();
// Get adjacent nodes from current node
var curConnected = graph[current]; // Get layer of edges from current
var neighborIdx = []; // List of nodes with edges
var idx = curConnected.indexOf(1); // Get first edge connection
while (idx !== -1) {
neighborIdx.push(idx); // Add to list of neighbors
idx = curConnected.indexOf(1, idx + 1); // Keep on searching
}
// Loop through neighbors and get lengths
for (var j = 0; j < neighborIdx.length; j++) {
// Increment distance for nodes traversed
if (nodesLen[neighborIdx[j]] === Infinity) {
nodesLen[neighborIdx[j]] = nodesLen[current] + 1;
queue.push(neighborIdx[j]); // Add new neighbors to queue
}
}
}
return nodesLen;
}
```

View File

@ -0,0 +1,175 @@
---
id: 587d8257367417b2b2512c7c
title: 二分探索木に要素が存在するかを調べる
challengeType: 1
forumTopicId: 301623
dashedName: check-if-an-element-is-present-in-a-binary-search-tree
---
# --description--
二分探索木について大まかに理解できたので、もう少し詳しく見ていきましょう。 二分探索木は、検索、挿入、削除という一般的操作の平均ケースでは対数時間計算量、最悪ケースでは線形時間計算量になります。 なぜでしょうか? これらの基本操作のそれぞれで、木の中の要素を見つける (または、挿入の場合は挿入先を見つける) 必要があります。また、各親ノードのツリー構造上、操作は左または右に分岐し、残りの木の半分のサイズを完全に排除します。 そのため検索は木のノード数の対数に比例し、これらの操作は平均ケースで対数時間計算量になります。 しかし最悪ケースについてはどうでしょうか? では、`10`, `12`, `17`, `25` という値を左から右に足していくことで、木を構成してみましょう。 二分探索木のルールに従って、`12``10` の右に、`17` をその右に、そして `25` をその右に追加します。 出来上がった木はリンクリストに似ており、`25` を見つけるために木を走査するには、すべての要素を線形に走査する必要があります。 したがって、最悪ケースでは線形時間計算量になります。 ここでの問題は、木が平衡でないことです。 それが何を意味するのかについては、以降のチャレンジでもう少し詳しく説明します。
# --instructions--
このチャレンジでは、私たちの木に対するユーティリティを作成します。 整数値を入力として受け取り、二分探索木でその値が存在するかどうかのブール値を返す、`isPresent` メソッドを記述してください。
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `isPresent` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.isPresent == 'function';
})()
);
```
`isPresent` メソッドは、木に追加された要素の有無を正しく調べる必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.isPresent !== 'function') {
return false;
}
test.add(4);
test.add(7);
test.add(411);
test.add(452);
return (
test.isPresent(452) &&
test.isPresent(411) &&
test.isPresent(7) &&
!test.isPresent(100)
);
})()
);
```
`isPresent` は、木が空であるケースを処理する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.isPresent !== 'function') {
return false;
}
return test.isPresent(5) == false;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
return searchTree(node);
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.isPresent = function (value) {
var current = this.root
while (current) {
if (value === current.value) {
return true;
}
current = value < current.value ? current.left : current.right;
}
return false;
}
}
```

View File

@ -0,0 +1,136 @@
---
id: 5cc0c1b32479e176caf3b422
title: 木が二分探索木であるかを調べる
challengeType: 1
forumTopicId: 301624
dashedName: check-if-tree-is-binary-search-tree
---
# --description--
二分探索木がどのようなものかはもう分かったので、このチャレンジでは、ある木が二分探索木であるかどうかを知る方法を学びます。
二分探索木の主な特徴は、ノードが整然と順序付けられることです。 ノードは、子ノードの値が親ノード以上なのか (右)、親ノードより小さいのか (左) に基づいて、最大 2 つの子ノード (右か左、またはその両方) を持ちます。
# --instructions--
このチャレンジでは、あなたの木に対するユーティリティを作成します。 木を入力として受け取り、その木が二分探索木であるかどうかのブール値を返す、JavaScript メソッド `isBinarySearchTree` を記述してください。 可能な限り再帰を使用してください。
# --hints--
二分探索木は、`isBinarySearchTree()` で調べられたときに true を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
test.push(1);
test.push(5);
test.push(3);
test.push(2);
test.push(4);
return isBinarySearchTree(test) == true;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype.push = function(val) {
var root = this.root;
if (!root) {
this.root = new Node(val);
return;
}
var currentNode = root;
var newNode = new Node(val);
while (currentNode) {
if (val < currentNode.value) {
if (!currentNode.left) {
currentNode.left = newNode;
break;
} else {
currentNode = currentNode.left;
}
} else {
if (!currentNode.right) {
currentNode.right = newNode;
break;
} else {
currentNode = currentNode.right;
}
}
}
};
```
## --seed-contents--
```js
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
}
function isBinarySearchTree(tree) {
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
}
function isBinarySearchTree(tree) {
if (tree.root == null) {
return null;
} else {
let isBST = true;
function checkTree(node) {
if (node.left != null) {
const left = node.left;
if (left.value > node.value) {
isBST = false;
} else {
checkTree(left);
}
}
if (node.right != null) {
const right = node.right;
if (right.value < node.value) {
isBST = false;
} else {
checkTree(right);
}
}
}
checkTree(tree.root);
return isBST;
}
};
```

View File

@ -0,0 +1,235 @@
---
id: 587d8255367417b2b2512c75
title: 循環キューを作成する
challengeType: 1
forumTopicId: 301625
dashedName: create-a-circular-queue
---
# --description--
このチャレンジでは、循環キューを作成します。 循環キューとは、コレクションの末尾にデータを書き込んだ後にコレクションの先頭から上書きを始めるキューです。 このタイプのデータ構造は、特定の状況で便利です。 例えば、ストリーミングメディアに循環キューを使用できます。 キューがいっぱいになると、新しいメディアデータが古いデータを上書きします。
この概念を分かりやすく説明するために、次のような、長さが `5` の配列を使います。
```js
[null, null, null, null, null]
^Read @ 0
^Write @ 0
```
今、読み取りと書き込みの両方が位置 `0` にあります。 ここでキューは `a``b``c` という 3 つの新しいレコードを取得します。 キューは次のようになりました。
```js
[a, b, c, null, null]
^Read @ 0
^Write @ 3
```
読み取りヘッドは、値を読み取るときに、次のように値を削除したり保持したりできます。
```js
[null, null, null, null, null]
^Read @ 3
^Write @ 3
```
次に、値 `d``e``f` をキューに書き込みましょう。 書き込みが配列の末尾に達すると、先頭に戻って書き込みが行われます。
```js
[f, null, null, d, e]
^Read @ 3
^Write @ 1
```
このアプローチは一定量のメモリを必要としますが、他のアプローチと比べ、はるかに大きなサイズのファイルを処理できます。
# --instructions--
このチャレンジでは、循環キューを実装してください。 循環キューには、キューからの読み取りとキューへの書き込みを可能にする `enqueue` メソッドと `dequeue` メソッドが必要です。 キューの作成時にそのサイズ指定に使用できる整数引数を、クラス自体が受け入れる必要があります。 このクラスの最初のバージョンが、コードエディタ内に既に用意されています。
要素をキューに入れると、書き込みポインタは前に進み、キューの末尾に達したら先頭に戻ります。 `enqueue` メソッドは、成功した場合、キューに追加された要素を返す必要があります。それ以外の場合は、`null` を返します。
同様に、要素をキューから取り除くと読み取りポインタが前進する必要があります。 要素をキューから取り除く際は、その要素を返す必要があります。 要素をキューから取り除けない場合は、`null` を返す必要があります。
書き込みポインタが読み取りポインタを追い越せないようにする必要があります (このクラスは、まだ読み取っていないデータを上書きすることはできません)。また、読み取りポインタは、書き込まれた過去のデータを前進させることはできません。
# --hints--
`enqueue` メソッドは、循環キューに要素を追加する必要があります。
```js
assert(
(function () {
var test = new CircularQueue(3);
test.enqueue(17);
test.enqueue(32);
test.enqueue(591);
var print = test.print();
return print[0] === 17 && print[1] === 32 && print[2] === 591;
})()
);
```
読み取りポインタを追い越して要素をキューに入れてはいけません。
```js
assert(
(function () {
var test = new CircularQueue(3);
test.enqueue(17);
test.enqueue(32);
test.enqueue(591);
test.enqueue(13);
test.enqueue(25);
test.enqueue(59);
var print = test.print();
return print[0] === 17 && print[1] === 32 && print[2] === 591;
})()
);
```
`dequeue` メソッドは、キューから要素を取り除く必要があります。
```js
assert(
(function () {
var test = new CircularQueue(3);
test.enqueue(17);
test.enqueue(32);
test.enqueue(591);
return (
test.dequeue() === 17 && test.dequeue() === 32 && test.dequeue() === 591
);
})()
);
```
要素がキューから取り除かれた後、キュー内におけるその要素の位置が `null` にリセットされる必要があります。
```js
assert(
(function () {
var test = new CircularQueue(3);
test.enqueue(17);
test.enqueue(32);
test.enqueue(672);
test.dequeue();
test.dequeue();
var print = test.print();
return print[0] === null && print[1] === null && print[2] === 672;
})()
);
```
書き込みポインタを越えてキューから取り除こうとすると `null` が返される必要があります。この場合、書き込みポインタは前進しません。
```js
assert(
(function () {
var test = new CircularQueue(3);
test.enqueue(17);
test.enqueue(32);
test.enqueue(591);
return (
test.dequeue() === 17 &&
test.dequeue() === 32 &&
test.dequeue() === 591 &&
test.dequeue() === null &&
test.dequeue() === null &&
test.dequeue() === null &&
test.dequeue() === null &&
test.enqueue(100) === 100 &&
test.dequeue() === 100
);
})()
);
```
# --seed--
## --seed-contents--
```js
class CircularQueue {
constructor(size) {
this.queue = [];
this.read = 0;
this.write = 0;
this.max = size - 1;
while (size > 0) {
this.queue.push(null);
size--;
}
}
print() {
return this.queue;
}
enqueue(item) {
// Only change code below this line
// Only change code above this line
}
dequeue() {
// Only change code below this line
// Only change code above this line
}
}
```
# --solutions--
```js
class CircularQueue {
constructor(size) {
this.queue = [];
this.read = 0;
this.write = 0;
this.max = size - 1;
while (size > 0) {
this.queue.push(null);
size--;
}
}
print() {
return this.queue;
}
enqueue(item) {
// Only change code below this line
console.log(this.write, this.max);
if (this.queue[this.write] === null) {
this.queue[this.write++] = item;
if (this.write > this.max) {
this.write = 0;
}
return item;
}
return null;
// Only change code above this line
}
dequeue() {
// Only change code below this line
if (this.queue[this.read] !== null) {
let item = this.queue[this.read];
this.queue[this.read++] = null;
if (this.read > this.max) {
this.read = 0;
}
return item;
}
return null;
// Only change code above this line
}
}
```

View File

@ -0,0 +1,216 @@
---
id: 587d825a367417b2b2512c87
title: 二重リンクリストを作成する
challengeType: 1
forumTopicId: 301626
dashedName: create-a-doubly-linked-list
---
# --description--
これまでに作成したリンクリストは、すべて単独でリンクされたリストです。 ここでは<dfn>二重リンクリスト</dfn>を作成します。 名前が示すように、二重リンクリスト内のノードは、リスト内の次ノードと前ノードへの参照を持っています。
これにより両方向でリストを走査することができますが、すべてのノードにリスト内の前ノードへの参照を追加する必要があるため、より多くのメモリを使用することになります。
# --instructions--
`Node` オブジェクトが既に用意され、`DoublyLinkedList` が開始しています。 二重リンクリストに、`add``remove` と呼ばれる 2 つのメソッドを追加しましょう。 `add` メソッドは与えられた要素をリストに追加する必要があります。`remove` メソッドは、リスト内で、与えられた要素のすべての出現を削除する必要があります。
これらのメソッドを記述する際は、先頭または末尾の要素の削除など、起こり得るエッジケースを慎重に処理してください。 また、空のリスト上で要素を削除すると、`null` が返される必要があります。
# --hints--
DoublyLinkedList データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
return typeof test == 'object';
})()
);
```
DoublyLinkedList に add というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
if (test.add == undefined) {
return false;
}
return typeof test.add == 'function';
})()
);
```
DoublyLinkedList に remove というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
if (test.remove == undefined) {
return false;
}
return typeof test.remove == 'function';
})()
);
```
また、空のリストから要素を削除すると、null が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
return test.remove(100) == null;
})()
);
```
add メソッドはリストに要素を追加する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
test.add(5);
test.add(6);
test.add(723);
return test.print().join('') == '56723';
})()
);
```
各ノードは前のノードを追跡する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
test.add(50);
test.add(68);
test.add(73);
return test.printReverse().join('') == '736850';
})()
);
```
先頭の要素はリストから削除可能である必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
test.add(25);
test.add(35);
test.add(60);
test.remove(25);
return test.print().join('') == '3560';
})()
);
```
末尾の要素はリストから削除可能である必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
test.add(25);
test.add(35);
test.add(60);
test.remove(60);
return test.print().join('') == '2535';
})()
);
```
# --seed--
## --after-user-code--
```js
DoublyLinkedList.prototype = Object.assign(
DoublyLinkedList.prototype,
{
print() {
if (this.head == null) {
return null;
} else {
var result = new Array();
var node = this.head;
while (node.next != null) {
result.push(node.data);
node = node.next;
};
result.push(node.data);
return result;
};
},
printReverse() {
if (this.tail == null) {
return null;
} else {
var result = new Array();
var node = this.tail;
while (node.prev != null) {
result.push(node.data);
node = node.prev;
};
result.push(node.data);
return result;
};
}
});
```
## --seed-contents--
```js
var Node = function(data, prev) {
this.data = data;
this.prev = prev;
this.next = null;
};
var DoublyLinkedList = function() {
this.head = null;
this.tail = null;
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,260 @@
---
id: 587d825b367417b2b2512c8e
title: ハッシュテーブルを作成する
challengeType: 1
forumTopicId: 301627
dashedName: create-a-hash-table
---
# --description--
このチャレンジでは、ハッシュテーブルについて学びます。 ハッシュテーブルは、連想配列、すなわちキーと値のペアのマッピング (例えば、これまでに学んだオブジェクトやマップ) を実装するために使用されます。 例えば、JavaScript オブジェクトはハッシュテーブルとして実装することができます (実際の実装は実行環境によって異なります)。 ハッシュテーブルの仕組みは、キー入力を受け取り、決定論的方法でこのキーを何らかの数値にハッシュすることです。 この数値は、関連付けられた値が格納される際の実際のキーとして使用されます。 次に、同じキーにアクセスしようとすると、ハッシュ関数はそのキーを処理して同じ数値結果を返し、それは関連付けられた値の検索に使用されます。 これにより、平均ケースでの検索時間は非常に効率的な O(1) になります。
ハッシュテーブルは、指定された範囲内で配列インデックスを生成するハッシュ関数を持つ配列として実装できます。 この方法では、ハッシュ関数と同様に配列サイズの選択が重要です。 例えば、ハッシュ関数が 2 つの異なるキーに対して同じ値を生成したらどうなりますか? これは衝突と呼ばれます。 衝突を処理する方法の一つは、キーと値のペアを両方ともそのインデックスに格納することです。 その場合、そのどちらかを検索するとき、あなたが探しているキーを見つけるために大量の要素に対して検索を繰り返す必要があります。 優れたハッシュ関数は、高い検索効率を維持するために衝突を最小限に抑えます。
ここではハッシュ法やハッシュテーブル実装を詳しく知る必要はなく、それらの大まかな仕組みを理解すれば十分です。
# --instructions--
ハッシュテーブルの基本的な機能を作成しましょう。 単純なハッシュ関数が既に用意されています。 関数 `hash` に文字列値を渡すと、ストレージのキーとして使用できるハッシュ値が返されます。 このハッシュ値に基づいて要素を `this.collection` オブジェクトに格納します。 `add``remove``lookup` という 3 つのメソッドを作成してください。 最初のメソッドで、ハッシュテーブルに追加するキーと値のペアを受け入れます。 2 番目のメソッドで、キーを渡すときにキーと値のペアを削除します。 3 番目のメソッドで、キーを受け入れ、関連付けられた値を返すか、キーが存在しない場合は `null` を返します。
衝突を考慮しながらコードを記述してください!
**注:** `remove` メソッドのテストは、`add` メソッドと `lookup` メソッドが正しく実装されるまで合格しません。
# --hints--
HashTable データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
return typeof test === 'object';
})()
);
```
HashTable に add メソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
return typeof test.add === 'function';
})()
);
```
HashTable に lookup メソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
return typeof test.lookup === 'function';
})()
);
```
HashTable に remove メソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
return typeof test.remove === 'function';
})()
);
```
add メソッドはキーと値のペアを追加し、lookup メソッドは与えられたキーに関連付けられた値を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
test.add('key', 'value');
return test.lookup('key') === 'value';
})()
);
```
remove メソッドはキーを入力として受け入れ、関連付けられたキーと値のペアを削除する必要があります。
```js
assert(
(function () {
var test = false;
var hashValue = hash('key');
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
test.add('key', 'value');
test.remove('key');
return !test.collection.hasOwnProperty(hashValue);
})()
);
```
remove メソッドは、キーと値の正しいペアのみを削除する必要があります。
```js
assert(
(function () {
var test = false;
var hashValue = hash('key');
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
test.add('key', 'value');
test.add('yek', 'value');
test.add('altKey', 'value');
test.remove('yek');
if (test.lookup('yek') || !test.lookup('key') || !test.lookup('altKey')) {
return false;
}
test.remove('key');
return !test.collection.hasOwnProperty(hashValue) && test.lookup('altKey');
})()
);
```
要素はハッシュ関数を使用して追加される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
called = 0;
test.add('key1', 'value1');
test.add('key2', 'value2');
test.add('key3', 'value3');
return called >= 3 && called % 3 === 0;
})()
);
```
ハッシュテーブルは衝突を処理する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof HashTable !== 'undefined') {
test = new HashTable();
}
called = 0;
test.add('key1', 'value1');
test.add('1key', 'value2');
test.add('ke1y', 'value3');
return (
test.lookup('key1') === 'value1' &&
test.lookup('1key') == 'value2' &&
test.lookup('ke1y') == 'value3'
);
})()
);
```
# --seed--
## --before-user-code--
```js
var called = 0;
var hash = string => {
called++;
var hash = 0;
for (var i = 0; i < string.length; i++) {
hash += string.charCodeAt(i);
}
return hash;
};
```
## --seed-contents--
```js
var called = 0;
var hash = string => {
called++;
var hashed = 0;
for (var i = 0; i < string.length; i++) {
hashed += string.charCodeAt(i);
}
return hashed;
};
var HashTable = function() {
this.collection = {};
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
var called = 0;
var hash = (string) => {
called++;
var hash = 0;
for (var i = 0; i < string.length; i++) { hash += string.charCodeAt(i); }
return hash;
};
var HashTable = function() {
this.collection = {};
// Only change code below this line
this.add = function(key, val) {
var theHash = hash(key);
if (!this.collection.hasOwnProperty(theHash)) {
this.collection[theHash] = {};
}
this.collection[theHash][key] = val;
}
this.remove = function(key) {
var theHash = hash(key);
var hashedObj = this.collection[theHash];
if (hashedObj.hasOwnProperty(key)) {
delete hashedObj[key];
}
if (!Object.keys(hashedObj).length) {
delete this.collection[theHash];
}
}
this.lookup = function(key) {
var theHash = hash(key);
if (this.collection.hasOwnProperty(theHash)) {
return this.collection[theHash][key];
}
return null
}
// Only change code above this line
};
```

View File

@ -0,0 +1,146 @@
---
id: 587d8251367417b2b2512c62
title: リンクリスト・クラスを作成する
challengeType: 1
forumTopicId: 301628
dashedName: create-a-linked-list-class
---
# --description--
`linked list` (リンクリスト) クラスを作成しましょう。 どのリンクリストでも、まずは基本プロパティ、すなわち `head` (リストの最初の要素) と `length` (リストの要素数) を定義する必要があります。 リストの最後の要素に `tail` を組み込んだリンクリストの実装も時々見かけますが、今はこの 2 つだけを使いましょう。 リンクリストに要素を追加するたびに、`length` プロパティが 1 ずつ増分される必要があります。
リンクリストに要素を追加する方法が必要なので、最初に作成したいのは `add` メソッドです。
リストが空の場合、リンクリストに要素を追加するのは簡単です。その要素を `Node` クラスにラップし、そのノードをリンクリストの `head` に割り当てるだけです。
しかし、このリストに既に 1 つ以上のメンバーがある場合はどうなるでしょう? どうすればリストに要素を追加できるでしょうか? リンクリストの各ノードに `next` プロパティがあることを思い出してください。 リストにノードを追加するには、リスト内の最後のノードを探し、最後のノードの `next` プロパティが新しいノードを指すようにします。 (ヒント: ノードの `next` プロパティが `null` のとき、リンクリストの末尾に到達したことが分かります。)
# --instructions--
リンクリストにプッシュした最初のノードを `head` に割り当てる add メソッドを記述してください。割り当ての後、ノードを追加するたびに、そのノードは前のノードの `next` プロパティによって参照される必要があります。
リストの `length` は、リンクリストに要素が追加されるたびに 1 ずつ増加する必要があります。
# --hints--
`LinkedList` クラスに `add` メソッドが必要です。
```js
assert(
(function () {
var test = new LinkedList();
return typeof test.add === 'function';
})()
);
```
`LinkedList` クラスは、追加された最初のノードに `head` を割り当てる必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
return test.head().element === 'cat';
})()
);
```
`LinkedList` クラスの以前の `node` は、作成された最新ノードへの参照を持つ必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('fish');
return test.head().next.element === 'dog' && test.head().next.next.element === 'fish';
})()
);
```
`LinkedList` クラスの `size` は、リンクリスト内のノードの数と同じである必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
return test.size() === 2;
})()
);
```
# --seed--
## --seed-contents--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.head = function(){
return head;
};
this.size = function(){
return length;
};
this.add = function(element){
// Only change code below this line
// Only change code above this line
};
}
```
# --solutions--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.head = function(){
return head;
};
this.size = function(){
return length;
};
this.add = function(element){
// Only change code below this line
if (head == null) {
head = new Node(element);
}
else {
let currentNode = head;
while (currentNode.next != null) {
// currentNode.next will be last node of linked list after loop
currentNode = currentNode.next;
}
currentNode.next = new Node(element);
}
length++;
// Only change code above this line
};
}
```

View File

@ -0,0 +1,204 @@
---
id: 8d5823c8c441eddfaeb5bdef
title: マップデータ構造を作成する
challengeType: 1
forumTopicId: 301629
dashedName: create-a-map-data-structure
---
# --description--
次のいくつかのチャレンジでは、マップとハッシュテーブルについて学びます。 マップはキーと値のペアを格納するデータ構造です。 JavaScript では、これらをオブジェクトとして利用できます。 マップは、キー値に基づいて格納された要素の迅速な検索を可能にする、非常に一般的で便利なデータ構造です。
# --instructions--
自分だけのマップを作る練習をしましょう。 JavaScript オブジェクトは、ここで書けるものよりもはるかに効率的なマップ構造を提供しているので、ここでの主な目的は学習のために練習することです。 ただし、JavaScript オブジェクトは特定の操作のみを提供します。 カスタム操作を定義したい場合はどうなるでしょう? ここで提供されている `Map` オブジェクトを JavaScript `object` のラッパーとして使用します。 Map オブジェクトに対する以下のメソッドと操作を作成してください。
<ul>
<li><code>add</code><code>key、value</code> のペアを受け入れてマップに追加します</li>
<li><code>remove</code> はキーを受け入れ、関連付けられた <code>key、value</code> のペア を削除します</li>
<li><code>get</code><code>key</code> を受け入れ、格納された <code>value</code> を返します</li>
<li><code>has</code><code>key</code> を受け入れ、キーが存在する場合は <dfn>true</dfn> を返し、そうでない場合は <dfn>false</dfn> を返します</li>
<li><code>values</code> はマップ内のすべての値の配列を返します</li>
<li><code>size</code> はマップ内の要素数を返します</li>
<li><code>clear</code> はマップを空にします</li>
</ul>
# --hints--
Map データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
return typeof test == 'object';
})()
);
```
Map オブジェクトには add、remove、get、has、value、clear、size の各メソッドが必要です 。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
return (
typeof test.add == 'function' &&
typeof test.remove == 'function' &&
typeof test.get == 'function' &&
typeof test.has == 'function' &&
typeof test.values == 'function' &&
typeof test.clear == 'function' &&
typeof test.size == 'function'
);
})()
);
```
add メソッドはマップに要素を追加する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
test.add(5, 6);
test.add(2, 3);
test.add(2, 5);
return test.size() == 2;
})()
);
```
has メソッドは、追加された要素に対して true を、存在しない要素に対して false を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
test.add('test', 'value');
return test.has('test') && !test.has('false');
})()
);
```
get メソッドはキーを入力として受け入れ、関連付けられた値を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
test.add('abc', 'def');
return test.get('abc') == 'def';
})()
);
```
values メソッドは、マップに格納されているすべての値を、文字列の配列として返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
test.add('a', 'b');
test.add('c', 'd');
test.add('e', 'f');
var vals = test.values();
return (
vals.indexOf('b') != -1 &&
vals.indexOf('d') != -1 &&
vals.indexOf('f') != -1
);
})()
);
```
clear メソッドはマップを空にし、size メソッドはマップに存在する要素の数を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof Map !== 'undefined') {
test = new Map();
}
test.add('b', 'b');
test.add('c', 'd');
test.remove('asdfas');
var init = test.size();
test.clear();
return init == 2 && test.size() == 0;
})()
);
```
# --seed--
## --seed-contents--
```js
var Map = function() {
this.collection = {};
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
var Map = function() {
this.collection = {};
// Only change code below this line
this.add = function(key,value) {
this.collection[key] = value;
}
this.remove = function(key) {
delete this.collection[key];
}
this.get = function(key) {
return this.collection[key];
}
this.has = function(key) {
return this.collection.hasOwnProperty(key)
}
this.values = function() {
return Object.values(this.collection);
}
this.size = function() {
return Object.keys(this.collection).length;
}
this.clear = function() {
for(let item of Object.keys(this.collection)) {
delete this.collection[item];
}
}
// Only change code above this line
};
```

View File

@ -0,0 +1,231 @@
---
id: 587d8255367417b2b2512c74
title: 優先度付きキュークラスを作成する
challengeType: 1
forumTopicId: 301630
dashedName: create-a-priority-queue-class
---
# --description--
このチャレンジでは、優先度付きキューを作成します。 優先度付きキューとは、要素の優先度を指定する追加情報をその要素が持てるという、特殊なタイプのキューです。 優先度は単純に整数で表すことができます。 ある数列要素がキューから取り出されるかどうかの決定は、その要素の位置よりも優先度に基づきます。 優先度の高い要素が優先度の低い要素の後にキューに追加されると、優先度の高い要素は他のすべての要素よりも先にキューから取り出されます。
例えば、3 つの要素を持つ優先度付きキューがあるとします。
```js
[['kitten', 2], ['dog', 2], ['rabbit', 2]]
```
ここでは、2 番目の値 (整数) が要素の優先度を表します。 優先度が `1``['human', 1]` をキューに入れると (優先度の数値が小さいほど優先されると仮定)、その要素はキューから最初に取り出されます。 コレクションは次のようになります。
```js
[['human', 1], ['kitten', 2], ['dog', 2], ['rabbit', 2]]
```
コードエディタ内に `PriorityQueue` の最初の部分が記述されています。 優先度を付けて要素を追加する `enqueue` メソッド、要素を削除して返す `dequeue` メソッド、キューの要素数を返す `size` メソッド、キューの先頭にある要素を返す `front` メソッド、そして最後に、キューが空の場合は `true`、空でない場合は `false` を返す `isEmpty` メソッドを追加してください。
`enqueue` は、上記のフォーマット (`['human', 1]`) の要素を受け入れる必要があります。ここで、`1` は優先度を表します。 `dequeue``front` は、その要素の優先度ではなく名前のみを返す必要があります。
# --hints--
`PriorityQueue` クラスに `enqueue` メソッドが必要です。
```js
assert(
(function () {
var test = new PriorityQueue();
return typeof test.enqueue === 'function';
})()
);
```
`PriorityQueue` クラスに `dequeue` メソッドが必要です。
```js
assert(
(function () {
var test = new PriorityQueue();
return typeof test.dequeue === 'function';
})()
);
```
`PriorityQueue` クラスに `size` メソッドが必要です。
```js
assert(
(function () {
var test = new PriorityQueue();
return typeof test.size === 'function';
})()
);
```
`PriorityQueue` クラスに `front` メソッドが必要です。
```js
assert(
(function () {
var test = new PriorityQueue();
return typeof test.front === 'function';
})()
);
```
`PriorityQueue` クラスに `isEmpty` メソッドが必要です。
```js
assert(
(function () {
var test = new PriorityQueue();
return typeof test.isEmpty === 'function';
})()
);
```
`PriorityQueue` クラスは、要素がキューから出し入れされる際、 `size` メソッドを使用して現在の要素数を正しく追跡する必要があります。
```js
assert(
(function () {
var test = new PriorityQueue();
test.enqueue(['David Brown', 2]);
test.enqueue(['Jon Snow', 1]);
var size1 = test.size();
test.dequeue();
var size2 = test.size();
test.enqueue(['A', 3]);
test.enqueue(['B', 3]);
test.enqueue(['C', 3]);
return size1 === 2 && size2 === 1 && test.size() === 4;
})()
);
```
`front` メソッドは、要素がキューから出し入れされる際、キューの先頭にある正しい要素を返す必要があります。
```js
assert(
(function () {
var test = new PriorityQueue();
test.enqueue(['David Brown', 2]);
var front1 = test.front();
test.enqueue(['Jon Snow', 1]);
var front2 = test.front();
test.dequeue();
test.enqueue(['A', 3]);
var front3 = test.front();
test.enqueue(['B', 3]);
test.enqueue(['C', 3]);
test.dequeue();
var front4 = test.front();
return (
front1 === 'David Brown' &&
front2 === 'Jon Snow' &&
front3 === 'David Brown' &&
front4 === 'A'
);
})()
);
```
`isEmpty` メソッドは、キューが空の場合に `true` を返す必要があります。
```js
assert(
(function () {
var test = new PriorityQueue();
test.enqueue(['A', 1]);
test.enqueue(['B', 1]);
test.dequeue();
var first = test.isEmpty();
test.dequeue();
return !first && test.isEmpty();
})()
);
```
優先度付きキューは、優先度の低い要素よりも先に優先度の高い要素を返し、そうしない場合は先入れ先出しの順序で返す必要があります。
```js
assert(
(function () {
var test = new PriorityQueue();
test.enqueue(['A', 5]);
test.enqueue(['B', 5]);
test.enqueue(['C', 5]);
test.enqueue(['D', 3]);
test.enqueue(['E', 1]);
test.enqueue(['F', 7]);
var result = [];
result.push(test.dequeue());
result.push(test.dequeue());
result.push(test.dequeue());
result.push(test.dequeue());
result.push(test.dequeue());
result.push(test.dequeue());
return result.join('') === 'EDABCF';
})()
);
```
# --seed--
## --seed-contents--
```js
function PriorityQueue () {
this.collection = [];
this.printCollection = function() {
console.log(this.collection);
};
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function PriorityQueue() {
this.collection = [];
this.printCollection = function () {
console.log(this.collection);
};
// Only change code below this line
this.enqueue = function (newitem) {
if (this.isEmpty()) {
return this.collection.push(newitem);
}
this.collection = this.collection.reverse();
var found_index = this.collection.findIndex(function (item) {
return newitem[1] >= item[1];
});
if (found_index === -1) {
this.collection.push(newitem);
} else {
this.collection.splice(found_index, 0, newitem);
}
this.collection = this.collection.reverse();
};
this.dequeue = function () {
if (!this.isEmpty()) {
return this.collection.shift()[0];
} else {
return "The queue is empty.";
}
};
this.size = function () {
return this.collection.length;
};
this.front = function () {
return this.collection[0][0];
};
this.isEmpty = function () {
return this.size() > 0 ? false : true;
};
// Only change code above this line
}
```

View File

@ -0,0 +1,174 @@
---
id: 587d8250367417b2b2512c60
title: キュークラスを作成する
challengeType: 1
forumTopicId: 301631
dashedName: create-a-queue-class
---
# --description--
スタックと同様に、キューは要素の集まりです。 しかしスタックとは異なり、キューは FIFO (先入れ先出し) の原則に従います。 キューに追加された要素はキューのテール (末尾) にプッシュされ、取り除くことができる要素はキューの先頭にある要素だけです。
キューは配列を使用して表すことができますが、スタックと同じように、ここではキューに対する制御量を制限したいのです。
キュークラスの 2 つの主なメソッドは enqueue と dequeue です。 enqueue メソッドは要素をキューの末尾にプッシュし、dequeue メソッドはキューの先頭にある要素を削除して返します。 他の便利なメソッドとしては front、size、isEmpty があります。
# --instructions--
要素をキューの末尾にプッシュする `enqueue` メソッド、先頭の要素を削除して返す `dequeue` メソッド、先頭の要素を確認するための `front` メソッド、長さを示す `size` メソッド、および、キューが空かどうかを調べる `isEmpty` メソッドを記述してください。
# --hints--
`Queue` クラスに `enqueue` メソッドが必要です。
```js
assert(
(function () {
var test = new Queue();
return typeof test.enqueue === 'function';
})()
);
```
`Queue` クラスに `dequeue` メソッドが必要です。
```js
assert(
(function () {
var test = new Queue();
return typeof test.dequeue === 'function';
})()
);
```
`Queue` クラスに `front` メソッドが必要です。
```js
assert(
(function () {
var test = new Queue();
return typeof test.front === 'function';
})()
);
```
`Queue` クラスに `size` メソッドが必要です。
```js
assert(
(function () {
var test = new Queue();
return typeof test.size === 'function';
})()
);
```
`Queue` クラスに `isEmpty` メソッドが必要です。
```js
assert(
(function () {
var test = new Queue();
return typeof test.isEmpty === 'function';
})()
);
```
`dequeue` メソッドはキューの先頭の要素を削除して返す必要があります。
```js
assert(
(function () {
var test = new Queue();
test.enqueue('Smith');
test.enqueue('John');
return test.dequeue() === 'Smith';
})()
);
```
`front` メソッドはキューの先頭の要素の値を返す必要があります。
```js
assert(
(function () {
var test = new Queue();
test.enqueue('Smith');
test.enqueue('John');
return test.front() === 'Smith';
})()
);
```
`size` メソッドはキューの長さを返す必要があります。
```js
assert(
(function () {
var test = new Queue();
test.enqueue('Smith');
return test.size() === 1;
})()
);
```
`isEmpty` メソッドは、キュー内に要素がある場合に `false` を返す必要があります。
```js
assert(
(function () {
var test = new Queue();
test.enqueue('Smith');
return !test.isEmpty();
})()
);
```
# --seed--
## --seed-contents--
```js
function Queue() {
var collection = [];
this.print = function() {
console.log(collection);
};
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function Queue () {
var collection = [];
this.print = function() {
console.log(collection);
};
// Only change code below this line
this.enqueue = function(item) {
collection.push(item);
}
this.dequeue = function() {
return collection.shift();
}
this.front = function() {
return collection[0];
}
this.size = function(){
return collection.length;
}
this.isEmpty = function() {
return collection.length === 0 ? true : false;
}
// Only change code above this line
}
```

View File

@ -0,0 +1,219 @@
---
id: 8d1323c8c441eddfaeb5bdef
title: セットクラスを作成する
challengeType: 1
forumTopicId: 301632
dashedName: create-a-set-class
---
# --description--
この課題では、「セット (集合)」と呼ばれる抽象的なデータ構造を模倣するために、`Set` という名前のクラスを作成します。 セットは配列と似ていますが、重複した値を含むことはできません。 セットの典型的な使用方法は、単純に要素の有無を確認することです。 次の例を見れば、ES6 `Set` オブジェクトの仕組みが分かります。
```js
const set1 = new Set([1, 2, 3, 5, 5, 2, 0]);
console.log(set1);
// output: {1, 2, 3, 5, 0}
console.log(set1.has(1));
// output: true
console.log(set1.has(6));
// output: false
```
まず、セットに値が存在しない場合は、セットコレクションに値を追加する add メソッドを作成します。 次に、値が既に存在する場合は、セットコレクションから値を削除する remove メソッドを作成します。 最後に、セットコレクション内の要素の数を返す size メソッドを作成します。
# --instructions--
セットコレクションに一意の値を追加する `add` メソッドを作成し、値が正常に追加された場合は `true`、それ以外の場合は `false` を返してください。
値を受け入れてそれがセット内に存在するかどうかを調べる、`remove` メソッドを作成してください。 値が存在する場合、このメソッドはセットコレクションからそれを削除し、`true` を返す必要があります。 値が存在しない場合は、`false` を返す必要があります。 セットコレクションのサイズを返す `size` メソッドを作成してください。
# --hints--
`Set` クラスに `add` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.add === 'function';
})()
);
```
`add` メソッドは重複値を追加してはいけません。
```js
assert(
(function () {
var test = new Set();
test.add('a');
test.add('b');
test.add('a');
var vals = test.values();
return vals[0] === 'a' && vals[1] === 'b' && vals.length === 2;
})()
);
```
`add` メソッドは、値が正常に追加された場合に `true` を返す必要があります。
```js
assert(
(function () {
var test = new Set();
var result = test.add('a');
return result != undefined && result === true;
})()
);
```
`add` メソッドは、重複値が追加された場合に `false` を返す必要があります。
```js
assert(
(function () {
var test = new Set();
test.add('a');
var result = test.add('a');
return result != undefined && result === false;
})()
);
```
`Set` クラスに `remove` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.remove === 'function';
})()
);
```
`remove` メソッドは、セット内に存在する要素のみを削除する必要があります。
```js
assert.deepEqual(
(function () {
var test = new Set();
test.add('a');
test.add('b');
test.remove('c');
return test.values();
})(),
['a', 'b']
);
```
`remove` メソッドは、指定された要素をセットから削除する必要があります。
```js
assert(
(function () {
var test = new Set();
test.add('a');
test.add('b');
test.remove('a');
var vals = test.values();
return vals[0] === 'b' && vals.length === 1;
})()
);
```
`Set` クラスに `size` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.size === 'function';
})()
);
```
`size` メソッドはコレクション内の要素の数を返す必要があります。
```js
assert(
(function () {
var test = new Set();
test.add('a');
test.add('b');
test.remove('a');
return test.size() === 1;
})()
);
```
# --seed--
## --seed-contents--
```js
class Set {
constructor() {
// Dictionary will hold the items of our set
this.dictionary = {};
this.length = 0;
}
// This method will check for the presence of an element and return true or false
has(element) {
return this.dictionary[element] !== undefined;
}
// This method will return all the values in the set
values() {
return Object.values(this.dictionary);
}
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
class Set {
constructor() {
this.dictionary = {};
this.length = 0;
}
has(element) {
return this.dictionary[element] !== undefined;
}
values() {
return Object.values(this.dictionary);
}
add(element) {
if (!this.has(element)) {
this.dictionary[element] = element;
this.length++;
return true;
}
return false;
}
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
size() {
return this.length;
}
}
```

View File

@ -0,0 +1,167 @@
---
id: 587d8250367417b2b2512c5f
title: スタッククラスを作成する
challengeType: 1
forumTopicId: 301633
dashedName: create-a-stack-class
---
# --description--
前のセクションでは、スタックとは何か、配列を使用してスタックを表すにはどうすれば良いかについて説明しました。 このセクションでは、独自のスタッククラスを作成します。 配列を使ってスタックを作成することはできますが、スタックに対する制御量を制限するのがベストです。 スタックには、`push` メソッドと `pop` メソッド以外にも便利なメソッドがあります。 スタッククラスに `peek``isEmpty``clear` メソッドを追加しましょう。
# --instructions--
スタックの一番上に要素をプッシュする `push` メソッド、スタックの一番上の要素を削除して返す `pop` メソッド、スタックの一番上の要素を見る `peek` メソッド、スタックが空かどうかを調べる `isEmpty` メソッド、および、スタックからすべての要素を削除する `clear` メソッドを記述してください。 今回は、コレクションのコンソールログを取得する `print` ヘルパーメソッドを追加しました (通常、スタックにはこれがありませんが)。
# --hints--
`Stack` クラスに `push` メソッドが必要です。
```js
assert(
(function () {
var test = new Stack();
return typeof test.push === 'function';
})()
);
```
`Stack` クラスに `pop` メソッドが必要です。
```js
assert(
(function () {
var test = new Stack();
return typeof test.pop === 'function';
})()
);
```
`Stack` クラスに `peek` メソッドが必要です。
```js
assert(
(function () {
var test = new Stack();
return typeof test.peek === 'function';
})()
);
```
`Stack` クラスに `isEmpty` メソッドが必要です。
```js
assert(
(function () {
var test = new Stack();
return typeof test.isEmpty === 'function';
})()
);
```
`Stack` クラスに `clear` メソッドが必要です。
```js
assert(
(function () {
var test = new Stack();
return typeof test.clear === 'function';
})()
);
```
`peek` メソッドはスタックの一番上の要素を返す必要があります。
```js
assert(
(function () {
var test = new Stack();
test.push('CS61');
test.push('CS50');
return test.peek() === 'CS50' && test.peek() === 'CS50';
})()
);
```
`pop` メソッドはスタックの一番上の要素を削除する必要があります。
```js
assert(
(function () {
var test = new Stack();
test.push('CS61');
test.push('CS50');
return test.pop() === 'CS50' && test.pop() === 'CS61';
})()
);
```
スタックに要素が含まれていない場合、`isEmpty` メソッドは true を返す必要があります。
```js
assert(
(function () {
var test = new Stack();
return test.isEmpty();
})()
);
```
`clear` メソッドはスタックのすべての要素を削除する必要があります。
```js
assert(
(function () {
var test = new Stack();
test.push('CS61');
test.push('CS50');
test.clear();
return test.isEmpty();
})()
);
```
# --seed--
## --seed-contents--
```js
function Stack() {
var collection = [];
this.print = function() {
console.log(collection);
};
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
class Stack {
constructor() {
this.collection = [];
}
print() {
console.log(this.collection);
}
push(val) {
this.collection.push(val);
}
pop() {
return this.collection.pop();
}
peek() {
return this.collection[this.collection.length - 1];
}
isEmpty() {
return this.collection.length === 0;
}
clear() {
return (this.collection.length = 0);
}
}
```

View File

@ -0,0 +1,151 @@
---
id: 587d8259367417b2b2512c84
title: トライ探索木を作成する
challengeType: 1
forumTopicId: 301634
dashedName: create-a-trie-search-tree
---
# --description--
二分探索木の次は、トライ (trie) と呼ばれる別のタイプのツリー構造を見てみましょう。 トライは、文字列を保持するためや、より一般的には、キーが文字列である連想配列や動的データセットを保持するために広く使われる、順序付き探索木です。 それらは、多数のキーの接頭辞が重複している場合に (例えば辞書内のすべての単語)、データセットを格納することに非常に適しています。 二分木とは異なり、ノードは実際の値と関連付けられません。 代わりに、ノードへの経路が特定のキーを表します。 例えば、文字列 "code" をトライに格納したい場合、c — o — d — e の文字のそれぞれに 1 つずつ、計 4 つのノードがあります。 これらすべてのノードを通る経路をたどると、文字列 "code" が作成されます。私たちはその経路をキーとして保存します。 次に、文字列 "coding" を追加したいとします。そのキーは、d の後に分岐する前の "code" の最初の 3 つのノードを共有します。 こうすれば、大規模なデータセットを非常にコンパクトに保存できます。 また、保存する文字列の長さに完全に限定されるため、検索を非常に素早く行えます。 さらに、二分木とは異なり、ノードは任意の数の子ノードを格納できます。 上の例から分かるように、後の走査でも引き続きキーを取得できるように、そのキーの末尾を持つノードに何らかのメタデータを格納することが一般的です。 例えば、上の例でコードを追加した場合、"code" の "e" は以前に入力されたキーの末尾を表すということを、何らかの方法で知る必要があります。 そうしなければ、コードを追加したときにこの情報は完全に失われます。
# --instructions--
単語を格納するためのトライを作成しましょう。 そのトライは、`add` メソッドで単語を受け入れ、それらをトライデータ構造に格納します。 また、与えられた文字列が単語かどうかを問い合わせるために `isWord` メソッドを使ったり、トライに格納されたすべての単語を取得するために `print` メソッドを使ったりできます。 `isWord` はブール値を返し、print はこれらすべての単語の配列を文字列値として返す必要があります。 このデータ構造が正しく実装されていることを確認するために、木の各ノードに `Node` 構造が用意されています。 各ードは、JavaScript Map オブジェクトである `keys` プロパティを持つオブジェクトです。 これには、各ノードの有効なキーである個々の文字が格納されます。 また、各ノードには `end` プロパティが既に作成されており、ノードが単語の終了を表す場合にこのプロパティを `true` に設定することができます。
# --hints--
Trie に add メソッドが必要です。
```js
assert(
(function testTrie() {
var test = false;
if (typeof Trie !== 'undefined') {
test = new Trie();
} else {
return false;
}
return typeof test.add == 'function';
})()
);
```
Trie に print メソッドが必要です。
```js
assert(
(function testTrie() {
var test = false;
if (typeof Trie !== 'undefined') {
test = new Trie();
} else {
return false;
}
return typeof test.print == 'function';
})()
);
```
Trie に isWord メソッドが必要です。
```js
assert(
(function testTrie() {
var test = false;
if (typeof Trie !== 'undefined') {
test = new Trie();
} else {
return false;
}
return typeof test.isWord == 'function';
})()
);
```
print メソッドは、トライに追加されたすべての値を文字列の配列として返す必要があります。
```js
assert(
(function testTrie() {
var test = false;
if (typeof Trie !== 'undefined') {
test = new Trie();
} else {
return false;
}
test.add('jump');
test.add('jumps');
test.add('jumped');
test.add('house');
test.add('mouse');
var added = test.print();
return (
added.indexOf('jump') != -1 &&
added.indexOf('jumps') != -1 &&
added.indexOf('jumped') != -1 &&
added.indexOf('house') != -1 &&
added.indexOf('mouse') != -1 &&
added.length == 5
);
})()
);
```
isWord メソッドは、トライに追加された単語に対してのみ true を返し、他のすべての単語に対して false を返す必要があります。
```js
assert(
(function testTrie() {
var test = false;
if (typeof Trie !== 'undefined') {
test = new Trie();
} else {
return false;
}
test.add('hop');
test.add('hops');
test.add('hopped');
test.add('hoppy');
test.add('hope');
return (
test.isWord('hop') &&
!test.isWord('ho') &&
test.isWord('hopped') &&
!test.isWord('hopp') &&
test.isWord('hoppy') &&
!test.isWord('hoping')
);
})()
);
```
# --seed--
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
var Node = function() {
this.keys = new Map();
this.end = false;
this.setEnd = function() {
this.end = true;
};
this.isEnd = function() {
return this.end;
};
};
var Trie = function() {
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,45 @@
---
id: 587d825b367417b2b2512c8d
title: ES6 JavaScript マップを作成する
challengeType: 1
forumTopicId: 301635
dashedName: create-an-es6-javascript-map
---
# --description--
JavaScript の新バージョンでは、前回のチャレンジで手書きした機能の多くを提供する、組み込みの Map ブジェクトが提供されています。 This Map object, although similar to regular JavaScript objects, provides some useful functionality that normal objects lack. For example, an ES6 Map tracks the insertion order of items that are added to it. より網羅的なメソッドの概要を次に示します。`.has(key)` はキーの有無に基づいて true または false を返します。`.get(key)` はキーに関連付けられた値を返します。`.set(key, value)` は新しいキーと値のペアを設定します。`.delete(key)` はキーと値のペアを削除します。`.clear()` はすべてのキーと値のペアを削除します。`.entries()` は挿入順にすべてのキーの配列を返します。`.values()` は挿入順にすべての値の配列を返します。
# --instructions--
JavaScript Map オブジェクトを定義し、変数 myMap をそのオブジェクトに割り当ててください。 キーと値のペア `freeCodeCamp``Awesome!` (すばらしい!) を追加してください。
# --hints--
myMap オブジェクトが存在する必要があります。
```js
assert(typeof myMap === 'object');
```
myMap にはキーと値のペア `freeCodeCamp``Awesome!` が含まれている必要があります。
```js
assert(myMap.get('freeCodeCamp') === 'Awesome!');
```
# --seed--
## --seed-contents--
```js
```
# --solutions--
```js
const myMap = new Map();
myMap.set("freeCodeCamp", "Awesome!");
```

View File

@ -0,0 +1,92 @@
---
id: 587d8254367417b2b2512c70
title: ES6 で Set を作成する・Set に追加する
challengeType: 1
forumTopicId: 301636
dashedName: create-and-add-to-sets-in-es6
---
# --description--
これまで ES5 を使って作業してきた方も、これから ES6 で同じようなことを行います。 その方がはるかに簡単です。 ES6 には `Set` というデータ構造が組み込まれており、これまで手作業で書いていた操作の多くが既に用意されています。 それを見てみましょう。
新しい空のセット (集合) を作成するには次のようにします。
```js
var set = new Set();
```
1 つの値を持つセットを作成できます。
```js
var set = new Set(1);
```
配列を使用してセットを作成できます。
```js
var set = new Set([1, 2, 3]);
```
セットを作成したら、`add` メソッドを使用して任意の値を追加できます。
```js
var set = new Set([1, 2, 3]);
set.add([4, 5, 6]);
```
セットは重複値を含むことができないデータ構造であることを思い出してください。
```js
var set = new Set([1, 2, 3, 1, 2, 3]);
// set contains [1, 2, 3] only
```
# --instructions--
この演習では、`1、2、3、'Taco'、'Cat'、'Awesome'` という値のセットを返してください。
# --hints--
`Set` には `1、2、3、Taco、Cat、Awesome` という値のみを含める必要があります。
```js
assert(
(function () {
var test = checkSet();
return (
test.size == 6 &&
test.has(1) &&
test.has(2) &&
test.has(3) &&
test.has('Taco') &&
test.has('Cat') &&
test.has('Awesome')
);
})()
);
```
# --seed--
## --seed-contents--
```js
function checkSet() {
var set = new Set([1, 2, 3, 3, 2, 1, 2, 3, 1]);
// Only change code below this line
// Only change code above this line
console.log(Array.from(set));
return set;
}
checkSet();
```
# --solutions--
```js
function checkSet(){var set = new Set([1,2,3,'Taco','Cat','Awesome']);
return set;}
```

View File

@ -0,0 +1,216 @@
---
id: 587d8258367417b2b2512c80
title: 二分探索木の葉ノードを削除する
challengeType: 1
forumTopicId: 301637
dashedName: delete-a-leaf-node-in-a-binary-search-tree
---
# --description--
これは、二分探索木でやや難しい操作を実装する 3 つのチャレンジの 1 つ目、「削除」です。 削除がなぜ難しいかというと、ノードを削除すると木の中でリンクが切れてしまうからです。 二分木構造が維持されるように、これらのリンクを注意深く作り直す必要があります。 つまり、場合によっては削除の際に木の中を再配置する必要があります。 一般的に、ノードを削除しようとすると次の 3 つのケースのいずれかが起こります。「葉ノード」: 削除対象ノードは子を持っていません。 「子が 1 つ」: 削除対象ノードは子を 1 つ持っています。 「子が 2 つ」: 削除対象ノードは子を 2 つ持っています。 葉ノードを削除するのは簡単で、単純にそれを削除します。 1 つの子を持つノードを削除することも比較的簡単です。単純に削除し、その親を、削除したノードの子とリンクさせます。 しかし 2 つの子を持つノードを削除するのは少しやっかいです。親木に再接続する必要のある子ノードが 2 つ生じるからです。 3 つ目のチャレンジで、このケースに対処する方法を見ていきます。 さらに、削除を処理する際には、いくつかのエッジケースに注意する必要があります。 木が空だったらどうでしょうか? 削除するノードが根ノードである場合はどうなるでしょうか? 木に 2 つの要素しかない場合はどうでしょうか? まずは、葉ノードを削除する最初のケースを処理しましょう。
# --instructions--
二分木に対して `remove` というメソッドを作成してください。 ここに、削除操作のロジックを構築します。 まず、現在の木で削除しようとしているノードを見つける関数を remove 内に作成します。 木の中にそのノードが存在しない場合、`remove``null` を返す必要があります。 対象ノードが子を持たない葉ノードの場合、それへの親参照を `null` に設定する必要があります。 これにより、ノードが木から完全に削除されます。 これを行うには、削除しようとしているノードの親も追跡する必要があります。 また、対象ノードが持つ子の数を追跡するための手段を作ることも有用です。そうすれば、その削除がどのケースに該当するかを判断できるからです。 次のチャレンジでは、第 2 および 第 3 のケースを処理します。 頑張ってください!
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `remove` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.remove == 'function';
})()
);
```
空の木から要素を削除しようすると、`null` が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
return test.remove(100) == null;
})()
);
```
存在しない要素を削除しようとすると、`null` が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(15);
test.add(30);
return test.remove(100) == null;
})()
);
```
根ノードに子がない場合は、削除すると根が `null` に設定される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(500);
test.remove(500);
return test.inorder() == null;
})()
);
```
`remove` メソッドは、葉ノードを木から削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(5);
test.add(3);
test.add(7);
test.add(6);
test.add(10);
test.add(12);
test.remove(3);
test.remove(12);
test.remove(10);
return test.inorder().join('') == '567';
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
return searchTree(node);
}
},
inorder: function() {
if (this.root == null) {
return null;
} else {
var result = new Array();
function traverseInOrder(node) {
if (node.left != null) {
traverseInOrder(node.left);
}
result.push(node.value);
if (node.right != null) {
traverseInOrder(node.right);
}
}
traverseInOrder(this.root);
return result;
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
}
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,285 @@
---
id: 587d8258367417b2b2512c81
title: 1 つの子を持つノードを二分探索木で削除する
challengeType: 1
forumTopicId: 301638
dashedName: delete-a-node-with-one-child-in-a-binary-search-tree
---
# --description--
ードを削除できるようになったので、2 つ目のケースに進みましょう。つまり、1 つの子を持つノードを削除します。 このケースでは、ノード 1 - 2 - 3 を持つ木があるとします。ここで、1 は根です。 2 を削除するには、1 から 3 への適切な参照を行うだけです。 より一般的には、子を 1 つだけ持つノードを削除するには、そのノードの親がツリー内の次のノードを参照するようにします。
# --instructions--
前回のチャレンジのタスクを実行する `remove` メソッドに、既にいくらかコードが記述されています。 削除の対象ノードとその親を見つけ、対象ノードが持つ子の数を定義してください。 ここでは、子を 1 つだけ持つ対象ノードに対して次のケースを追加しましょう。 ここで、その単一の子がツリー内の左側の枝なのか右側の枝なのかを判断し、このノードを指す正しい参照を親に設定する必要があります。 さらに、対象ノードが根ノードであるケース (すなわち親ノードが `null`) を考えてみましょう。 提供されている開始コードをすべて独自のものに書き換えても構いません (それがテストに合格するコードであれば)。
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `remove` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.remove == 'function';
})()
);
```
存在しない要素を削除しようとすると、`null` が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
return test.remove(100) == null;
})()
);
```
根ノードに子がない場合は、根ノードを削除すると根が `null` に設定される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(500);
test.remove(500);
return test.inorder() == null;
})()
);
```
`remove` メソッドは、葉ノードをツリーから削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(5);
test.add(3);
test.add(7);
test.add(6);
test.add(10);
test.add(12);
test.remove(3);
test.remove(12);
test.remove(10);
return test.inorder().join('') == '567';
})()
);
```
`remove` メソッドは、子を 1 つ持つノードを削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(-1);
test.add(3);
test.add(7);
test.add(16);
test.remove(16);
test.remove(7);
test.remove(3);
return test.inorder().join('') == '-1';
})()
);
```
2 つのードを持つ木の根を削除すると、2 番目のノードが根として設定される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(15);
test.add(27);
test.remove(15);
return test.inorder().join('') == '27';
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
return searchTree(node);
}
},
inorder: function() {
if (this.root == null) {
return null;
} else {
var result = new Array();
function traverseInOrder(node) {
if (node.left != null) {
traverseInOrder(node.left);
}
result.push(node.value);
if (node.right != null) {
traverseInOrder(node.right);
}
}
traverseInOrder(this.root);
return result;
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.remove = function(value) {
if (this.root === null) {
return null;
}
var target;
var parent = null;
// Find the target value and its parent
(function findValue(node = this.root) {
if (value == node.value) {
target = node;
} else if (value < node.value && node.left !== null) {
parent = node;
return findValue(node.left);
} else if (value < node.value && node.left === null) {
return null;
} else if (value > node.value && node.right !== null) {
parent = node;
return findValue(node.right);
} else {
return null;
}
}.bind(this)());
if (target === null) {
return null;
}
// Count the children of the target to delete
var children =
(target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
// Case 1: Target has no children
if (children === 0) {
if (target == this.root) {
this.root = null;
} else {
if (parent.left == target) {
parent.left = null;
} else {
parent.right = null;
}
}
}
// Case 2: Target has one child
// Only change code below this line
};
}
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,399 @@
---
id: 587d8258367417b2b2512c82
title: 2 つの子を持つノードを二分探索木で削除する
challengeType: 1
forumTopicId: 301639
dashedName: delete-a-node-with-two-children-in-a-binary-search-tree
---
# --description--
2 つの子を持つノードを削除するのは、最も実装が難しいケースです。 このようなノードを削除すると、元のツリー構造との接続が切れた 2 つの部分木が生じます。 どうすれば再接続できるでしょうか? 一つの方法は、削除対象ノードの右部分木で最小の値を見つけ、対象ノードをこの値に置き換えることです。 このような方法で置き換えると、削除対象ノードは、それが新しい親として持つ、左部分木にあるすべてのノードよりも必ず大きくなると同時に、それが新しい親として持つ、右部分木にあるすべてのノードよりも必ず小さくなります。 この置換が行われたら、置換ノードは右部分木から削除されなければなりません。 この操作でさえ用心が必要です。置換ノードが葉ノードであったり、それ自体が右部分木の親であったりする可能性があるためです。 それが葉ノードである場合は、それに対する親の参照を削除する必要があります。 葉ノードでない場合は、それは削除対象ノードの右側の子でなければなりません。 この場合、削除対象ノードの値を置換値に置き換え、削除対象ノードが置換ノードの右側の子を参照するように設定しなければなりません。
# --instructions--
最後に、`remove` メソッドで 3 つ目のケースを処理しましょう。 最初の 2 つのケースのために、今回もコードが用意されています。 2 つの子を持つ対象ノードを処理するコードを追加してください。 意識すべきエッジケースがありますか? 木にノードが 3 つしかない場合はどうでしょうか? これを終えれば、二分探索木の削除操作が完了します。 よくできました、これはかなり難しい問題です!
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `remove` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.remove == 'function';
})()
);
```
存在しない要素を削除しようとすると、`null` が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.remove == 'function' ? test.remove(100) == null : false;
})()
);
```
根ノードに子がない場合は、根ノードを削除すると根が `null` に設定される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
test.add(500);
test.remove(500);
return typeof test.remove == 'function' ? test.inorder() == null : false;
})()
);
```
`remove` メソッドは、葉ノードを木から削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
test.add(5);
test.add(3);
test.add(7);
test.add(6);
test.add(10);
test.add(12);
test.remove(3);
test.remove(12);
test.remove(10);
return typeof test.remove == 'function'
? test.inorder().join('') == '567'
: false;
})()
);
```
`remove` メソッドは、子を 1 つ持つノードを削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(-1);
test.add(3);
test.add(7);
test.add(16);
test.remove(16);
test.remove(7);
test.remove(3);
return test.inorder().join('') == '-1';
})()
);
```
2 つのードを持つ木の根を削除すると、2 番目のノードが根として設定される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(15);
test.add(27);
test.remove(15);
return test.inorder().join('') == '27';
})()
);
```
`remove` メソッドは二分探索木構造を維持しながら、2 つの子を持つノードを削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(1);
test.add(4);
test.add(3);
test.add(7);
test.add(9);
test.add(11);
test.add(14);
test.add(15);
test.add(19);
test.add(50);
test.remove(9);
if (!test.isBinarySearchTree()) {
return false;
}
test.remove(11);
if (!test.isBinarySearchTree()) {
return false;
}
test.remove(14);
if (!test.isBinarySearchTree()) {
return false;
}
test.remove(19);
if (!test.isBinarySearchTree()) {
return false;
}
test.remove(3);
if (!test.isBinarySearchTree()) {
return false;
}
test.remove(50);
if (!test.isBinarySearchTree()) {
return false;
}
test.remove(15);
if (!test.isBinarySearchTree()) {
return false;
}
return test.inorder().join('') == '147';
})()
);
```
3 つのノードを持つ木において根を削除できる必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.remove !== 'function') {
return false;
}
test.add(100);
test.add(50);
test.add(300);
test.remove(100);
return test.inorder().join('') == 50300;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
return searchTree(node);
}
},
inorder: function() {
if (this.root == null) {
return null;
} else {
var result = new Array();
function traverseInOrder(node) {
if (node.left != null) {
traverseInOrder(node.left);
}
result.push(node.value);
if (node.right != null) {
traverseInOrder(node.right);
}
}
traverseInOrder(this.root);
return result;
}
},
isBinarySearchTree() {
if (this.root == null) {
return null;
} else {
var check = true;
function checkTree(node) {
if (node.left != null) {
var left = node.left;
if (left.value > node.value) {
check = false;
} else {
checkTree(left);
}
}
if (node.right != null) {
var right = node.right;
if (right.value < node.value) {
check = false;
} else {
checkTree(right);
}
}
}
checkTree(this.root);
return check;
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.remove = function(value) {
if (this.root === null) {
return null;
}
var target;
var parent = null;
// Find the target value and its parent
(function findValue(node = this.root) {
if (value == node.value) {
target = node;
} else if (value < node.value && node.left !== null) {
parent = node;
return findValue(node.left);
} else if (value < node.value && node.left === null) {
return null;
} else if (value > node.value && node.right !== null) {
parent = node;
return findValue(node.right);
} else {
return null;
}
}.bind(this)());
if (target === null) {
return null;
}
// Count the children of the target to delete
var children =
(target.left !== null ? 1 : 0) + (target.right !== null ? 1 : 0);
// Case 1: Target has no children
if (children === 0) {
if (target == this.root) {
this.root = null;
} else {
if (parent.left == target) {
parent.left = null;
} else {
parent.right = null;
}
}
}
// Case 2: Target has one child
else if (children == 1) {
var newChild = target.left !== null ? target.left : target.right;
if (parent === null) {
target.value = newChild.value;
target.left = null;
target.right = null;
} else if (newChild.value < parent.value) {
parent.left = newChild;
} else {
parent.right = newChild;
}
target = null;
}
// Case 3: Target has two children
// Only change code below this line
};
}
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,208 @@
---
id: 587d825d367417b2b2512c96
title: 深さ優先探索
challengeType: 1
forumTopicId: 301640
dashedName: depth-first-search
---
# --description--
ここでは、<dfn>幅優先探索</dfn>と似ているが別のグラフ走査アルゴリズムである、<dfn>深さ優先探索</dfn>について学びます。
幅優先探索はソースノードからのエッジの長さを徐々に増やして検索しますが、<dfn>深さ優先探索</dfn>は、最初にエッジの経路のうちの 1 本をできるだけ遠くまで下ります。
経路の末端に到達すると、検索は訪問されていないエッジ経路を持つ最後のノードに引き返し、検索を続けます。
下のアニメーションはこのアルゴリズムの仕組みを示しています。 このアルゴリズムは一番上のノードから始まり、番号順にノードを訪問します。
<img class='img-responsive' src='https://camo.githubusercontent.com/aaad9e39961daf34d967c616edeb50abf3bf1235/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f372f37662f44657074682d46697273742d5365617263682e676966' />
幅優先探索とは異なり、1 つのノードを訪問するたびにすべての隣接ノードを訪れるわけではありません。 代わりに、最初に隣接ノードのいずれかを訪れ、その経路上に未訪問のノードがなくなるまで経路を下り続けます。
このアルゴリズムを実装するには、スタックを使用すると良いでしょう。 スタックは、最後に追加された要素が最初に削除されるような配列です。 これは、<dfn>後入れ先出し</dfn>のデータ構造とも呼ばれます。 スタックは、深さ優先探索アルゴリズムに役立ちます。なぜなら、スタックに隣接ノードを追加するとき、直近に追加された隣接ノードを最初に訪問してそれをスタックから取り除きたいからです。
このアルゴリズムの単純な出力は、与えられたノードから到達可能なノードのリストです。 したがって、訪問したノードの追跡も必要でしょう。
# --instructions--
無向の隣接行列 `graph` とノードラベル `root` をパラメータとして取る関数、`dfs()` を記述してください。 ノードラベルは単に `0` から `n - 1` の間の数値です (`n` はグラフ内のノードの総数)。
この関数は、`root` から到達可能なすべてのノードの配列を出力する必要があります。
# --hints--
`1` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` は、`0``1``2``3` を持つ配列を返す必要があります。
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 1);
})(),
[0, 1, 2, 3]
);
```
`1` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]]` は、4 つの要素を持つ配列を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 1);
})().length === 4
);
```
`3` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` は、`3` を持つ配列を返す必要があります。
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
return dfs(graph, 3);
})(),
[3]
);
```
`3` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 0]]` は、1 つの要素を持つ配列を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 0]
];
return dfs(graph, 3);
})().length === 1
);
```
`3` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]`は、`2``3` を持つ配列を返す必要があります。
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 3);
})(),
[2, 3]
);
```
`3` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` は、2 つの要素を持つ配列を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 3);
})().length === 2
);
```
`0` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` は、`0``1` を持つ配列を返す必要があります。
```js
assert.sameMembers(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 0);
})(),
[0, 1]
);
```
`0` を開始ノードとする入力グラフ `[[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]` は、2 つの要素を持つ配列を返す必要があります。
```js
assert(
(function () {
var graph = [
[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
];
return dfs(graph, 0);
})().length === 2
);
```
# --seed--
## --seed-contents--
```js
function dfs(graph, root) {
}
var exDFSGraph = [
[0, 1, 0, 0],
[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]
];
console.log(dfs(exDFSGraph, 3));
```
# --solutions--
```js
function dfs(graph, root) {
var stack = [];
var tempV;
var visited = [];
var tempVNeighbors = [];
stack.push(root);
while (stack.length > 0) {
tempV = stack.pop();
if (visited.indexOf(tempV) == -1) {
visited.push(tempV);
tempVNeighbors = graph[tempV];
for (var i = 0; i < tempVNeighbors.length; i++) {
if (tempVNeighbors[i] == 1) {
stack.push(i);
}
}
}
}
return visited;
}
```

View File

@ -0,0 +1,346 @@
---
id: 587d8257367417b2b2512c7d
title: 二分探索木の最小と最大の高さを見つける
challengeType: 1
forumTopicId: 301641
dashedName: find-the-minimum-and-maximum-height-of-a-binary-search-tree
---
# --description--
直前のチャレンジでは、木が不均衡になる (平衡でなくなる) 可能性のあるシナリオを説明しました。 平衡の概念を理解するために、木のもう一つの性質である「高さ」に注目してみましょう。 木の高さは、根ノードから、与えられた葉ノードまでの距離を表します。 分岐の多いツリー構造では経路によって高さが異なる場合がありますが、与えられた木には最小と最大の高さがあります。 平衡木の場合、これらの値の差は最大 1 です。 つまり平衡木では、すべての葉ノードが同じレベル内にあるか、または、同じレベル内でないとしても差は 1 レベル以内です。
平衡性は、木の操作効率を左右するので木にとって重要なものです。 直前のチャレンジで説明したように、ひどく不均衡な木では最悪ケースの時間計算量になってしまいます。 動的データセットを持つ木でこの問題を考慮するために、平衡木がよく使われます。 その一般的な例としては、AVL 木、赤黒木、B 木などがあります。 これらすべての木には、挿入や削除によって平衡でなくなった木を再び平衡にするための内部ロジックが追加されています。
**注:**「高さ」と似た性質として「深さ」があります。深さは、与えられたノードが根ノードからどれだけ離れているかを表します。
# --instructions--
私たちの二分木に対して 2 つのメソッド、`findMinHeight``findMaxHeight` を記述してください。 これらのメソッドは、与えられた二分木の中の最小と最大の高さの整数値をそれぞれ返す必要があります。 ノードが空の場合は、`-1` の高さを割り当てましょう (これは初期条件です)。 最後に、木が平衡であるかどうかに応じて `true` または `false` を返す 3 つ目のメソッド、`isBalanced` を追加してください。 木が平衡かどうかを決定するには、最初の 2 つのメソッドを使用できます。
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `findMinHeight` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.findMinHeight == 'function';
})()
);
```
二分探索木に `findMaxHeight` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.findMaxHeight == 'function';
})()
);
```
二分探索木に `isBalanced` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.isBalanced == 'function';
})()
);
```
`findMinHeight` メソッドは、木の最小の高さを返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.findMinHeight !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
return test.findMinHeight() == 1;
})()
);
```
`findMaxHeight` メソッドは、木の最大の高さを返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.findMaxHeight !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
return test.findMaxHeight() == 5;
})()
);
```
空の木は `-1` の高さを返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.findMaxHeight !== 'function') {
return false;
}
return test.findMaxHeight() == -1;
})()
);
```
`isBalanced` メソッドは、その木が不均衡な二分探索木である場合に `false` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.isBalanced !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
return test.isBalanced() === false;
})()
);
```
`isBalanced` メソッドは、その木が平衡な二分探索木である場合に `true` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.isBalanced !== 'function') {
return false;
}
test.add(10);
test.add(3);
test.add(22);
test.add(1);
test.add(4);
test.add(17);
test.add(32);
return test.isBalanced() === true;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
return searchTree(node);
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
this.findMinHeight = function(root = this.root) {
// empty tree.
if (root === null) {
return -1;
}
// leaf node.
if (root.left === null && root.right === null) {
return 0;
}
if (root.left === null) {
return this.findMinHeight(root.right) + 1;
}
if (root.right === null) {
return this.findMinHeight(root.left) + 1;
}
const lHeight = this.findMinHeight(root.left);
const rHeight = this.findMinHeight(root.right);
return Math.min(lHeight, rHeight) + 1;
};
this.findMaxHeight = function(root = this.root) {
// empty tree.
if (root === null) {
return -1;
}
// leaf node.
if (root.left === null && root.right === null) {
return 0;
}
if (root.left === null) {
return this.findMaxHeight(root.right) + 1;
}
if (root.right === null) {
return this.findMaxHeight(root.left) + 1;
}
const lHeight = this.findMaxHeight(root.left);
const rHeight = this.findMaxHeight(root.right);
return Math.max(lHeight, rHeight) + 1;
};
this.isBalanced = function(root = this.root) {
if (root === null) {
return true;
}
if (root.left === null && root.right === null) {
return true;
}
if (root.left === null) {
return this.findMaxHeight(root.right) <= 0;
}
if (root.right === null) {
return this.findMaxHeight(root.left) <= 0;
}
const lHeight = this.findMaxHeight(root.left);
const rHeight = this.findMaxHeight(root.right);
if (Math.abs(lHeight - rHeight) > 1) {
return false;
}
return this.isBalanced(root.left) && this.isBalanced(root.right);
};
}
```

View File

@ -0,0 +1,369 @@
---
id: 587d8256367417b2b2512c7a
title: 二分探索木の最小値と最大値を見つける
challengeType: 1
forumTopicId: 301642
dashedName: find-the-minimum-and-maximum-value-in-a-binary-search-tree
---
# --description--
このチャレンジでは、`findMin``findMax` の 2 つのメソッドを定義します。 これらのメソッドは、二分探索木の中の最小値と最大値を返す必要があります (今は、木に値を追加することについて考える必要はありません。値を追加するコードが既に用意されています)。 分からなくなったら、二分探索木において必ず真であるべき不変条件を思い出してください。つまり、左部分木はそれぞれがその親以下、右部分木はそれぞれがその親以上でなければなりません。 また、木は整数値のみを格納できるものとしましょう。 木が空の場合、どちらのメソッドも `null` を返す必要があります。
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `findMin` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.findMin == 'function';
})()
);
```
二分探索木に `findMax` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.findMax == 'function';
})()
);
```
`findMin` メソッドは、二分探索木の最小値を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.findMin !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
return test.findMin() == 1;
})()
);
```
`findMax` メソッドは、二分探索木の最大値を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.findMax !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
return test.findMax() == 87;
})()
);
```
`findMin` メソッドと `findMax` メソッドは、空の木の場合に `null` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.findMin !== 'function') {
return false;
}
if (typeof test.findMax !== 'function') {
return false;
}
return test.findMin() == null && test.findMax() == null;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
return searchTree(node);
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.findMin = function() {
// Empty tree.
if (!this.root) {
return null;
}
let currentNode = this.root;
while (currentNode.left) {
currentNode = currentNode.left;
}
return currentNode.value;
};
this.findMax = function() {
// Empty tree.
if (!this.root) {
return null;
}
let currentNode = this.root;
while (currentNode.right) {
currentNode = currentNode.right;
}
return currentNode.value;
};
this.add = function(value) {
// Empty tree.
if (!this.root) {
this.root = new Node(value);
return undefined;
}
return this.addNode(this.root, value);
};
this.addNode = function(node, value) {
// Check if value already exists.
if (node.value === value) return null;
if (value < node.value) {
if (node.left) {
return this.addNode(node.left, value);
} else {
node.left = new Node(value);
return undefined;
}
} else {
if (node.right) {
return this.addNode(node.right, value);
} else {
node.right = new Node(value);
return undefined;
}
}
};
this.isPresent = function(value) {
if (!this.root) {
return null;
}
return this.isNodePresent(this.root, value);
};
this.isNodePresent = function(node, value) {
if (node.value === value) return true;
if (value < node.value) {
return node.left ? this.isNodePresent(node.left, value) : false;
} else {
return node.right ? this.isNodePresent(node.right, value) : false;
}
return false;
};
this.findMinHeight = function() {
if (!this.root) {
return -1;
}
let heights = {};
let height = 0;
this.traverseTree(this.root, height, heights);
return Math.min(...Object.keys(heights));
};
this.findMaxHeight = function() {
if (!this.root) {
return -1;
}
let heights = {};
let height = 0;
this.traverseTree(this.root, height, heights);
return Math.max(...Object.keys(heights));
};
this.traverseTree = function(node, height, heights) {
if (node.left === null && node.right === null) {
return (heights[height] = true);
}
if (node.left) {
this.traverseTree(node.left, height + 1, heights);
}
if (node.right) {
this.traverseTree(node.right, height + 1, heights);
}
};
this.isBalanced = function() {
return this.findMaxHeight() > this.findMinHeight() + 1;
};
// DFS tree traversal.
this.inorder = function() {
if (!this.root) return null;
let result = [];
function traverseInOrder(node) {
if (node.left) traverseInOrder(node.left);
result.push(node.value);
if (node.right) traverseInOrder(node.right);
}
traverseInOrder(this.root);
return result;
};
this.preorder = function() {
if (!this.root) return null;
let result = [];
function traverseInOrder(node) {
result.push(node.value);
if (node.left) traverseInOrder(node.left);
if (node.right) traverseInOrder(node.right);
}
traverseInOrder(this.root);
return result;
};
this.postorder = function() {
if (!this.root) return null;
let result = [];
function traverseInOrder(node) {
if (node.left) traverseInOrder(node.left);
if (node.right) traverseInOrder(node.right);
result.push(node.value);
}
traverseInOrder(this.root);
return result;
};
// BFS tree traversal.
this.levelOrder = function() {
if (!this.root) return null;
let queue = [this.root];
let result = [];
while (queue.length) {
let node = queue.shift();
result.push(node.value);
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
return result;
};
this.reverseLevelOrder = function() {
if (!this.root) return null;
let queue = [this.root];
let result = [];
while (queue.length) {
let node = queue.shift();
result.push(node.value);
if (node.right) queue.push(node.right);
if (node.left) queue.push(node.left);
}
return result;
};
// Delete a leaf node.
}
let bst = new BinarySearchTree();
```

View File

@ -0,0 +1,144 @@
---
id: 587d825b367417b2b2512c8c
title: 最小ヒープでヒープ ソートを実装する
challengeType: 1
forumTopicId: 301643
dashedName: implement-heap-sort-with-a-min-heap
---
# --description--
要素の追加と削除ができるようになったので、ヒープを使える応用をいくつか見てみましょう。 ヒープは優先度付きキューを実装するためによく使用されます。なぜなら、優先度付きキューは常に、先頭に最大値または最小値の要素を格納するからです。 さらに、ヒープソートと呼ばれるソートアルゴリズムの実装にもヒープが使用されます。 その方法を見ていきましょう。 ヒープソートは、最大ヒープの逆である最小ヒープを使用します。 最小ヒープは常に、最小値である要素を根の位置に格納します。
ヒープソートの仕組みは、ソートされていない配列を取り、配列内の各要素を最小ヒープに追加し、次に最小ヒープからすべての要素を新しい配列に抽出するというものです。 最小ヒープ構造では、新しい配列に元の要素が必ず最小から最大の順序で格納されます。 これは、平均ケースと最悪ケースのパフォーマンスが O(nlog(n)) である最も効率的なソートアルゴリズムの一つです。
# --instructions--
最小ヒープを使ってヒープソートを実装しましょう。 ここでは、自分が書いた最大ヒープのコードを基にしても構いません。 `insert``remove``sort` の各メソッドを持つオブジェクト `MinHeap` を作成してください。 `sort` メソッドは、最小ヒープ内のすべての要素が最小から最大の順に格納されている配列を返す必要があります。
# --hints--
MinHeap データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof MinHeap !== 'undefined') {
test = new MinHeap();
}
return typeof test == 'object';
})()
);
```
MinHeap に insert というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MinHeap !== 'undefined') {
test = new MinHeap();
} else {
return false;
}
return typeof test.insert == 'function';
})()
);
```
MinHeap に remove というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MinHeap !== 'undefined') {
test = new MinHeap();
} else {
return false;
}
return typeof test.remove == 'function';
})()
);
```
MinHeap に sort というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MinHeap !== 'undefined') {
test = new MinHeap();
} else {
return false;
}
return typeof test.sort == 'function';
})()
);
```
sort メソッドは、最小ヒープに追加されたすべての要素がソート順に格納されている配列を返す必要があります。
```js
assert(
(() => {
if (typeof MinHeap === 'undefined') {
return false;
}
const heap = new MinHeap();
const arr = createRandomArray(25);
for (let i of arr) {
heap.insert(i);
}
const result = heap.sort();
arr.sort((a, b) => a - b);
for (let i = 0; i < arr.length; i++) {
if (arr[i] !== result[i]) {
return false;
}
}
return true;
})()
);
```
# --seed--
## --seed-contents--
```js
function isSorted(a){
for(let i = 0; i < a.length - 1; i++)
if(a[i] > a[i + 1])
return false;
return true;
}
// Generate a randomly filled array
function createRandomArray(size = 5){
let a = new Array(size);
for(let i = 0; i < size; i++)
a[i] = Math.floor(Math.random() * 100);
return a;
}
const array = createRandomArray(25);
var MinHeap = function() {
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,110 @@
---
id: 587d8256367417b2b2512c79
title: 接続行列
challengeType: 1
forumTopicId: 301644
dashedName: incidence-matrix
---
# --description--
グラフを表すもう一つの方法は、 <dfn>接続行列</dfn>に入れることです。
<dfn>接続行列</dfn> は二次元 (2D) 配列です。 一般に接続行列は、2 つの次元の間で 2 種類のクラスのオブジェクトを関連付けます。 このような行列は隣接行列に似ています。 しかし、行と列の意味がそれとは異なります。
グラフにはエッジとノードがあります。 この 2 つは、私たちが使う「オブジェクトの 2 種類のクラス」です。 この行列では、行がノード、列がエッジを表します。 したがって、行と列の数が違っていても構いません。
各列は一意のエッジを表します。 また、各エッジは 2 つのノードを接続します。 2 つのノードの間に 1 本のエッジがあることを示すために、特定の列の 2 行に 1 を入れます。 下に示したのは、ノード 1 とノード 3 の間に 1 本のエッジがある、3 ノードのグラフです。
<blockquote> 1<br> ---<br>1 | 1<br>2 | 0<br>3 | 1</blockquote>
4 本のエッジと 4 つのノードを持つ`接続行列`の例を示します。 列はエッジ、行はノード自体であることを思い出してください。
<blockquote> 1 2 3 4<br> --------<br>1 | 0 1 1 1<br>2 | 1 1 0 0<br>3 | 1 0 0 1<br>4 | 0 0 1 0</blockquote>
次のコードは、同じことを JavaScript で実装したものです。
```js
var incMat = [
[0, 1, 1, 1],
[1, 1, 0, 0],
[1, 0, 0, 1],
[0, 0, 1, 0]
];
```
有向グラフを作成するには、特定のノードを離れるエッジに `-1` を使用し、ノードに入るエッジに `1` を使用します。
```js
var incMatDirected = [
[ 0, -1, 1, -1],
[-1, 1, 0, 0],
[ 1, 0, 0, 1],
[ 0, 0, -1, 0]
];
```
グラフのエッジに <dfn>重み</dfn> を付けることもできます。 これまでに見てきたエッジは、単にエッジの有無が二項 (`0` または `1`) で表された、<dfn>重み付けされていない</dfn>エッジです。 用途によって重みを変えることができます。 異なる重みは 1 より大きい数字として表されます。
# --instructions--
5 つのノードと 4 本のエッジを持つ、無向グラフの接続行列を作成してください。 この行列は多次元配列でなければなりません。
これら 5 つのノードは次のような関係にあります。 1 本目のエッジは 1 番目と 2 番目のノードの間にあります。 2 本目のエッジは 2 番目と 3 番目のノードの間にあります。 3 本目のエッジは 3 番目と 5 番目のノードの間にあります。 4 本目のエッジは 4 番目と 2 番目のノードの間にあります。 すべてのエッジの重みは 1 であり、エッジの順序には意味があります。
# --hints--
`incMatUndirected` には 5 つのノードのみが含まれている必要があります。
```js
assert(
incMatUndirected.length === 5 &&
incMatUndirected
.map(function (x) {
return x.length === 4;
})
.reduce(function (a, b) {
return a && b;
})
);
```
1 番目と 2 番目のノードの間には 1 本目のエッジが必要です。
```js
assert(incMatUndirected[0][0] === 1 && incMatUndirected[1][0] === 1);
```
2 番目と 3 番目のードの間には、2 本目のエッジが必要です。
```js
assert(incMatUndirected[1][1] === 1 && incMatUndirected[2][1] === 1);
```
3 番目と 5 番目のードの間には、3 本目のエッジが必要です。
```js
assert(incMatUndirected[2][2] === 1 && incMatUndirected[4][2] === 1);
```
2 番目と 4 番目のードの間には、4 本目のエッジが必要です。
```js
assert(incMatUndirected[1][3] === 1 && incMatUndirected[3][3] === 1);
```
# --seed--
## --seed-contents--
```js
var incMatUndirected = [
];
```
# --solutions--
```js
var incMatUndirected = [[1, 0, 0, 0],[1, 1, 0, 1],[0, 1, 1, 0],[0, 0, 0, 1],[0, 0, 1, 0]];
```

View File

@ -0,0 +1,165 @@
---
id: 587d825a367417b2b2512c8a
title: 要素を最大ヒープに挿入する
challengeType: 1
forumTopicId: 301703
dashedName: insert-an-element-into-a-max-heap
---
# --description--
次に、別のツリーデータ構造である二分ヒープに進みます。 二分ヒープは、ヒーププロパティを満たす、部分的に順序付きの二分木です。 ヒーププロパティは、親ノードと子ノードの関係を指定します。 最大ヒープ (すべての親ノードがその子ノード以上であるようなヒープ)、または最小ヒープ (その逆であるヒープ) を持つことができます。 二分ヒープは完全な二分木でもあります。 つまり、木のすべてのレベルが完全に埋まっています。最後のレベルが部分的に埋まっている場合には、左から右に埋まります。
二分ヒープは、左右の参照を含むノードを持つツリー構造として実装できますが、ヒーププロパティに従って部分的に順序付けすれば、配列を使ってヒープを表現することができます。 ここでは親子関係に注目します。あらゆる親ノードの子と、あらゆる子ノードの親を、簡単な算術で計算することができます。
例えば、二分最小ヒープを次のような配列で表現することを考えてみましょう。
```js
[ 6, 22, 30, 37, 63, 48, 42, 76 ]
```
根ノードは最初の要素、`6` です。 根ノードの子は `22``30` です。 これらの値の配列インデックス間の関係を見てみると、`i` の子要素は `2 * i + 1` および `2 * i + 2` です。 同様に、インデックス `0` にある要素は、インデックス `1``2` にある 2 つの子の親です。 より一般的には、`Math.floor(i - 1) / 2)` を使用すれば、任意のインデックスにあるノードの親を見つけることができます。 二分木がどれほど大きくなってもこれらのパターンが当てはまります。 最後に、配列内の最初の要素をスキップするというわずかな調整で、この演算をさらに簡単にできます。 これを行うと、与えられたインデックス `i` にある任意の要素に対して次のような関係が作られます。
配列表現の例:
```js
[ null, 6, 22, 30, 37, 63, 48, 42, 76 ]
```
要素の左の子: `i * 2`
要素の右の子: `i * 2 + 1`
要素の親: `Math.floor(i / 2)`
この計算を理解してしまえば、配列表現を使うことは非常に便利です。なぜなら、子ノードへの参照を維持する必要がないので、この演算でノード位置が素早く決まり、メモリ使用量が減少するからです。
# --instructions--
手順: ここでは最大ヒープを作成してください。 まず、ヒープに要素を追加する `insert` メソッドを作成します。 挿入中は、ヒーププロパティを常に維持することが重要です。 つまり最大ヒープの場合、根要素は常に木の中で最大値を持ち、すべての親ノードは子ノードより大きくなければなりません。 ヒープの配列実装では、通常、これは次の 3 つのステップで実行されます。
<ol>
<li>配列の末尾に新しい要素を追加します。</li>
<li>要素が親より大きい場合は、それらを交換します。</li>
<li>新しい要素が親より小さくなるまで、または木の根に到達するまで、交換を続けます。</li>
</ol>
最後に、ヒープに追加されたすべての要素の配列を返す `print` メソッドを追加します。
# --hints--
MaxHeap データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
}
return typeof test == 'object';
})()
);
```
MaxHeap に insert というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
return typeof test.insert == 'function';
})()
);
```
MaxHeap に print というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
return typeof test.print == 'function';
})()
);
```
insert メソッドは最大ヒーププロパティに従って要素を追加する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
test.insert(50);
test.insert(100);
test.insert(700);
test.insert(32);
test.insert(51);
test.insert(800);
const result = test.print();
const solution = JSON.stringify([null,800,51,700,32,50,100]);
const solutionWithoutNull = JSON.stringify([800,51,700,32,50,100]);
return (result.length == 6) ? (JSON.stringify(result) == solutionWithoutNull) : (JSON.stringify(result) == solution);
})()
);
```
# --seed--
## --seed-contents--
```js
var MaxHeap = function() {
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
var MaxHeap = function() {
// Only change code below this line
this.heap = [];
this.parent = index => {
return Math.floor((index - 1) / 2);
}
this.insert = element => {
this.heap.push(element);
this.heapifyUp(this.heap.length - 1);
}
this.heapifyUp = index => {
let currentIndex = index,
parentIndex = this.parent(currentIndex);
while (currentIndex > 0 && this.heap[currentIndex] > this.heap[parentIndex]) {
this.swap(currentIndex, parentIndex);
currentIndex = parentIndex;
parentIndex = this.parent(parentIndex);
}
}
this.swap = (index1, index2) => {
[this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
}
this.print = () => {
return this.heap;
}
// Only change code above this line
};
```

View File

@ -0,0 +1,192 @@
---
id: 587d8259367417b2b2512c83
title: 二分木を反転させる
challengeType: 1
forumTopicId: 301704
dashedName: invert-a-binary-tree
---
# --description--
ここでは、二分木を反転させる関数を作成します。 与えられた二分木の左右を逆にして新しい木を作りましょう。 反転した木で通りがけ順走査を実行すると、元の木の通りがけ順走査とは逆の順にノードが探索されます。 これを行うための `invert` と呼ばれるメソッドを二分木に対して記述してください。 このメソッドを呼び出すことで現在のツリー構造が反転する必要があります。 線形時間計算量でこれをそのまま行えるのが理想です。 つまり、各ノードを 1 回訪れ、追加のメモリを使用せずに、走査しながら既存のツリー構造を変更します。 頑張ってください!
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `invert` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.invert == 'function';
})()
);
```
`invert` メソッドはツリー構造を正しく反転させる必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.invert !== 'function') {
return false;
}
test.add(4);
test.add(1);
test.add(7);
test.add(87);
test.add(34);
test.add(45);
test.add(73);
test.add(8);
test.invert();
return test.inorder().join('') == '877345348741';
})()
);
```
空の木を反転させると、`null` が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.invert !== 'function') {
return false;
}
return test.invert() == null;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left)
};
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
};
} else {
return null;
};
}
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
return searchTree(node);
};
},
inorder: function() {
if (this.root == null) {
return null;
} else {
var result = new Array();
function traverseInOrder(node) {
if (node.left != null) {
traverseInOrder(node.left);
};
result.push(node.value);
if (node.right != null) {
traverseInOrder(node.right);
};
}
traverseInOrder(this.root);
return result;
};
}
}
);
```
## --seed-contents--
```js
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = (tree) => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
this.invert = function(node = this.root) {
if (node) {
const temp = node.left;
node.left = node.right;
node.right = temp;
this.invert(node.left);
this.invert(node.right);
}
return node;
}
// Only change code above this line
}
```

View File

@ -0,0 +1,71 @@
---
id: 587d8250367417b2b2512c5e
title: スタックの仕組みを学ぶ
challengeType: 1
forumTopicId: 301705
dashedName: learn-how-a-stack-works
---
# --description--
机の上に本が積まれていることはよくあるでしょう。 テキストエディタの取り消し機能を使ったことがあるでしょう。 また、携帯電話の「戻る」ボタンを押してアプリを直前の表示に戻すことに慣れているでしょう。
そのすべてに共通する点は何でしょうか? それらはすべて、後方に走査できるようにデータを格納しています。
本の山の一番上にある本は、最後に置かれた本でした。 山の一番上からその本を取り除くと、最後の本より先に置かれた本が見え、本を取り除くたびに同じことが起こります。
そう考えると、上のすべての例で<dfn>後入れ先出し</dfn>タイプのサービスを受けていることになります。 これをコードを使って再現してみましょう。
このようなデータ保存は<dfn>スタック</dfn>と呼ばれます。 具体的には、JavaScript オブジェクトをスタックの一番上にプッシュする `push()` メソッドと、現在スタックの一番上にある JavaScript オブジェクトを削除する `pop()` メソッドを実装する必要があります。
# --instructions--
ここでは、配列で表現された宿題のスタックがあります。`"BIO12"` (生物 12) はスタックの一番下、`"PSY44"` (物理 44) は一番上です。
与えられた配列を変更し、上述の JavaScript メソッドを使用してそれを `stack` のように扱ってください。 一番上の要素 `"PSY44"` をスタックから削除します。 次に、スタックの新しい一番上の要素として `"CS50"` (コンピュータサイエンス 50) を追加します。
# --hints--
`homeworkStack` には 4 つの要素のみが含まれている必要があります。
```js
assert(homeworkStack.length === 4);
```
`homeworkStack` の最後の要素は `"CS50"` でなければなりません。
```js
assert(homeworkStack[3] === 'CS50');
```
`homeworkStack``"PSY44"` を含めることはできません。
```js
assert(homeworkStack.indexOf('PSY44') === -1);
```
`homeworkStack` の最初の宣言は変更しないでください。
```js
assert(
code.match(/=/g).length === 1 &&
/homeworkStack\s*=\s*\["BIO12"\s*,\s*"HIS80"\s*,\s*"MAT122"\s*,\s*"PSY44"\]/.test(
code
)
);
```
# --seed--
## --seed-contents--
```js
var homeworkStack = ["BIO12","HIS80","MAT122","PSY44"];
// Only change code below this line
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,219 @@
---
id: 587d8254367417b2b2512c6e
title: 2 つのデータセットの差集合を求める
challengeType: 1
forumTopicId: 301706
dashedName: perform-a-difference-on-two-sets-of-data
---
# --description--
この課題では、2 つのデータセットの差集合を求めます。 `difference` と呼ばれる メソッドを `Set` データ構造に作成します。 2 つのセットの差集合を求めるには、2 つのセットを比較して、最初のセットにはあるが 2 番目のセットにはない要素を返す必要があります。 このメソッドは、別の `Set` を引数として取り、2 つのセットの `difference` を返す必要があります。
例えば、`setA = ['a','b','c']` かつ `setB = ['a','b','d','e']` の場合、setA と setB の差集合は `setA.difference(setB) = ['c']` です。
# --hints--
`Set` クラスに `difference` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.difference === 'function';
})()
);
```
`difference` メソッドは適切なコレクションを返す必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setA.add('b');
setA.add('c');
setB.add('c');
setB.add('d');
var differenceSetAB = setA.difference(setB);
return (
differenceSetAB.size() === 2 &&
DeepEqual(differenceSetAB.values(), ['a', 'b'])
);
})()
);
```
# --seed--
## --seed-contents--
```js
class Set {
constructor() {
// This will hold the set
this.dictionary = {};
this.length = 0;
}
// This method will check for the presence of an element and return true or false
has(element) {
return this.dictionary[element] !== undefined;
}
// This method will return all the values in the set
values() {
return Object.keys(this.dictionary);
}
// This method will add an element to the set
add(element) {
if (!this.has(element)) {
this.dictionary[element] = true;
this.length++;
return true;
}
return false;
}
// This method will remove an element from a set
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
// This method will return the size of the set
size() {
return this.length;
}
// This is our union method
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
// This is our intersection method
intersection(set) {
const newSet = new Set();
let largeSet;
let smallSet;
if (this.dictionary.length > set.length) {
largeSet = this;
smallSet = set;
} else {
largeSet = set;
smallSet = this;
}
smallSet.values().forEach(value => {
if (largeSet.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
class Set {
constructor() {
this.dictionary = {};
this.length = 0;
}
has(element) {
return this.dictionary[element] !== undefined;
}
values() {
return Object.keys(this.dictionary);
}
add(element) {
if (!this.has(element)) {
this.dictionary[element] = true;
this.length++;
return true;
}
return false;
}
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
size() {
return this.length;
}
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
intersection(set) {
const newSet = new Set();
let largeSet;
let smallSet;
if (this.dictionary.length > set.length) {
largeSet = this;
smallSet = set;
} else {
largeSet = set;
smallSet = this;
}
smallSet.values().forEach(value => {
if (largeSet.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
difference(set) {
const newSet = new Set();
this.values().forEach(value => {
if (!set.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
}
```

View File

@ -0,0 +1,302 @@
---
id: 587d8254367417b2b2512c6f
title: 2 つのデータセットに対してサブセットチェックを実行する
challengeType: 1
forumTopicId: 301707
dashedName: perform-a-subset-check-on-two-sets-of-data
---
# --description--
この課題では、2 つのデータセットに対してサブセット (部分集合) テ ストを実行します。 `isSubsetOf` と呼ばれるメソッドを `Set` データ構造に作成します。 これは最初のセットを 2 番目のセットと比較し、最初のセットがすべて 2 番目のセットに含まれている場合に `true` を返します。
例えば、`setA = ['a','b']` かつ `setB = ['a','b','c','d']` の場合、 `setA``setB` のサブセットなので、`setA.isSubsetOf(setB)``true` を返す必要があります。
# --hints--
`Set` クラスに `isSubsetOf` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.isSubsetOf === 'function';
})()
);
```
最初の Set() が 2 番目の Set に含まれている必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setB.add('b');
setB.add('c');
setB.add('a');
setB.add('d');
var aIsSubsetOfB = setA.isSubsetOf(setB);
return aIsSubsetOfB === true;
})()
);
```
`['a', 'b'].isSubsetOf(['a', 'b', 'c', 'd'])``true` を返す必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setA.add('b');
setB.add('a');
setB.add('b');
setB.add('c');
setB.add('d');
var aIsSubsetOfB = setA.isSubsetOf(setB);
return aIsSubsetOfB === true;
})()
);
```
`['a', 'b', 'c'].isSubsetOf(['a', 'b'])``false` を返す必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setA.add('b');
setA.add('c');
setB.add('a');
setB.add('b');
var aIsSubsetOfB = setA.isSubsetOf(setB);
return aIsSubsetOfB === false;
})()
);
```
`[].isSubsetOf([])``true` を返す必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
var aIsSubsetOfB = setA.isSubsetOf(setB);
return aIsSubsetOfB === true;
})()
);
```
`['a', 'b'].isSubsetOf(['c', 'd'])``false` を返す必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setA.add('b');
setB.add('c');
setB.add('d');
var aIsSubsetOfB = setA.isSubsetOf(setB);
return aIsSubsetOfB === false;
})()
);
```
# --seed--
## --seed-contents--
```js
class Set {
constructor() {
// This will hold the set
this.dictionary = {};
this.length = 0;
}
// This method will check for the presence of an element and return true or false
has(element) {
return this.dictionary[element] !== undefined;
}
// This method will return all the values in the set
values() {
return Object.keys(this.dictionary);
}
// This method will add an element to the set
add(element) {
if (!this.has(element)) {
this.dictionary[element] = true;
this.length++;
return true;
}
return false;
}
// This method will remove an element from a set
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
// This method will return the size of the set
size() {
return this.length;
}
// This is our union method
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
// This is our intersection method
intersection(set) {
const newSet = new Set();
let largeSet;
let smallSet;
if (this.dictionary.length > set.length) {
largeSet = this;
smallSet = set;
} else {
largeSet = set;
smallSet = this;
}
smallSet.values().forEach(value => {
if (largeSet.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
difference(set) {
const newSet = new Set();
this.values().forEach(value => {
if (!set.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
class Set {
constructor() {
this.dictionary = {};
this.length = 0;
}
has(element) {
return this.dictionary[element] !== undefined;
}
values() {
return Object.keys(this.dictionary);
}
add(element) {
if (!this.has(element)) {
this.dictionary[element] = true;
this.length++;
return true;
}
return false;
}
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
size() {
return this.length;
}
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
intersection(set) {
const newSet = new Set();
let largeSet;
let smallSet;
if (this.dictionary.length > set.length) {
largeSet = this;
smallSet = set;
} else {
largeSet = set;
smallSet = this;
}
smallSet.values().forEach(value => {
if (largeSet.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
difference(set) {
const newSet = new Set();
this.values().forEach(value => {
if (!set.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
isSubsetOf(set) {
for(const value of this.values()){
if(!set.dictionary[value]) return false;
}
return true
}
}
```

View File

@ -0,0 +1,155 @@
---
id: 587d8253367417b2b2512c6c
title: 2 つのセットの和集合を求める
challengeType: 1
forumTopicId: 301708
dashedName: perform-a-union-on-two-sets
---
# --description--
この課題では、2 つのデータセットの和集合を求めます。 `union` と呼ばれるメソッドを `Set` データ構造に作成します。 このメソッドは、別の `Set` を引数として取り、重複する値を除外して、2 つのセットの `union` を返す必要があります。
例えば、`setA = ['a','b','c']` かつ `setB = ['a','b','d','e']` の場合、setA と setB の和集合は `setA.union(setB) = ['a', 'b', 'c', 'd', 'e']` です。
# --hints--
`Set` クラスに `union` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.union === 'function';
})()
);
```
The union of a Set containing values ["a", "b", "c"] and a Set containing values ["c", "d"] should return a new Set containing values ["a", "b", "c", "d"].
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setA.add('b');
setA.add('c');
setB.add('c');
setB.add('d');
var unionSetAB = setA.union(setB);
var final = unionSetAB.values();
return (
final.indexOf('a') !== -1 &&
final.indexOf('b') !== -1 &&
final.indexOf('c') !== -1 &&
final.indexOf('d') !== -1 &&
final.length === 4
);
})()
);
```
# --seed--
## --seed-contents--
```js
class Set {
constructor() {
// This will hold the set
this.dictionary = {};
this.length = 0;
}
// This method will check for the presence of an element and return true or false
has(element) {
return this.dictionary[element] !== undefined;
}
// This method will return all the values in the set
values() {
return Object.values(this.dictionary);
}
// This method will add an element to the set
add(element) {
if (!this.has(element)) {
this.dictionary[element] = element;
this.length++;
return true;
}
return false;
}
// This method will remove an element from a set
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
// This method will return the size of the set
size() {
return this.length;
}
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
class Set {
constructor() {
this.dictionary = {};
this.length = 0;
}
has(element) {
return this.dictionary[element] !== undefined;
}
values() {
return Object.values(this.dictionary);
}
add(element) {
if (!this.has(element)) {
this.dictionary[element] = element;
this.length++;
return true;
}
return false;
}
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
size() {
return this.length;
}
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
}
```

View File

@ -0,0 +1,184 @@
---
id: 587d8253367417b2b2512c6d
title: 2 つのデータセットの積集合を求める
challengeType: 1
forumTopicId: 301709
dashedName: perform-an-intersection-on-two-sets-of-data
---
# --description--
この課題では、2 つのデータセットの積集合を求めます。 `intersection` と呼ばれるメソッドを `Set` データ構造に作成します。 セットの積集合とは、2 つ以上のセットに共通するすべての値のことです。 このメソッドは、別の `Set` を引数として取り、2 つのセットの `intersection` を返す必要があります。
例えば、`setA = ['a','b','c']` かつ `setB = ['a','b','d','e']` の場合、setA と setB の積集合は `setA.intersection(setB) = ['a', 'b']` です。
# --hints--
`Set` クラスに `intersection` メソッドが必要です。
```js
assert(
(function () {
var test = new Set();
return typeof test.intersection === 'function';
})()
);
```
適切なコレクションが返される必要があります。
```js
assert(
(function () {
var setA = new Set();
var setB = new Set();
setA.add('a');
setA.add('b');
setA.add('c');
setB.add('c');
setB.add('d');
var intersectionSetAB = setA.intersection(setB);
return (
intersectionSetAB.size() === 1 && intersectionSetAB.values()[0] === 'c'
);
})()
);
```
# --seed--
## --seed-contents--
```js
class Set {
constructor() {
// This will hold the set
this.dictionary = {};
this.length = 0;
}
// This method will check for the presence of an element and return true or false
has(element) {
return this.dictionary[element] !== undefined;
}
// This method will return all the values in the set
values() {
return Object.keys(this.dictionary);
}
// This method will add an element to the set
add(element) {
if (!this.has(element)) {
this.dictionary[element] = true;
this.length++;
return true;
}
return false;
}
// This method will remove an element from a set
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
// This method will return the size of the set
size() {
return this.length;
}
// This is our union method
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
class Set {
constructor() {
this.dictionary = {};
this.length = 0;
}
has(element) {
return this.dictionary[element] !== undefined;
}
values() {
return Object.keys(this.dictionary);
}
add(element) {
if (!this.has(element)) {
this.dictionary[element] = true;
this.length++;
return true;
}
return false;
}
remove(element) {
if (this.has(element)) {
delete this.dictionary[element];
this.length--;
return true;
}
return false;
}
size() {
return this.length;
}
union(set) {
const newSet = new Set();
this.values().forEach(value => {
newSet.add(value);
})
set.values().forEach(value => {
newSet.add(value);
})
return newSet;
}
intersection(set) {
const newSet = new Set();
let largeSet;
let smallSet;
if (this.dictionary.length > set.length) {
largeSet = this;
smallSet = set;
} else {
largeSet = set;
smallSet = this;
}
smallSet.values().forEach(value => {
if (largeSet.dictionary[value]) {
newSet.add(value);
}
})
return newSet;
}
}
```

View File

@ -0,0 +1,151 @@
---
id: 587d825b367417b2b2512c8b
title: 最大ヒープから要素を削除する
challengeType: 1
forumTopicId: 301710
dashedName: remove-an-element-from-a-max-heap
---
# --description--
ヒープに要素を追加できるようになったので、要素を削除する方法を学びましょう。 要素の削除と挿入は、どちらも似たようなロジックが必要です。 最大ヒープでは一般に最大値を削除したいので、単に木の根からそれを抽出すれば良いのです。 これによって木のヒーププロパティが壊れるので、何らかの方法でそれを作り直す必要があります。 通常、最大ヒープの場合は次の方法でそれを行います。
<ol>
<li>ヒープ内の最後の要素を根の位置に移動します。</li>
<li>根の子のいずれかが根より大きい場合は、根を、より大きい値の子と交換します。</li>
<li>親が両方の子よりも大きくなるまで、または操作が木の最後のレベルに達するまで、交換を続けます。</li>
</ol>
# --instructions--
手順: `remove` と呼ばれるメソッドを最大ヒープに追加してください。 このメソッドは、最大ヒープに追加された最大値を返し、ヒープから削除する必要があります。 また、ヒーププロパティが維持されるようにヒープの順序を変更する必要があります。 要素を削除した後、ヒープに残っている次の最大の要素が根になる必要があります。
# --hints--
MaxHeap データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
}
return typeof test == 'object';
})()
);
```
MaxHeap に print というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
return typeof test.print == 'function';
})()
);
```
MaxHeap に insert というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
return typeof test.insert == 'function';
})()
);
```
MaxHeap に remove というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
return typeof test.remove == 'function';
})()
);
```
remove メソッドは max heap プロパティを維持しながら最大ヒープから最大要素を削除する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof MaxHeap !== 'undefined') {
test = new MaxHeap();
} else {
return false;
}
test.insert(30);
test.insert(300);
test.insert(500);
test.insert(10);
let result = [];
result.push(test.remove());
result.push(test.remove());
result.push(test.remove());
result.push(test.remove());
return result.join('') == '5003003010';
})()
);
```
# --seed--
## --seed-contents--
```js
var MaxHeap = function () {
this.heap = [];
this.parent = index => {
return Math.floor((index - 1) / 2);
}
this.insert = element => {
this.heap.push(element);
this.heapifyUp(this.heap.length - 1);
}
this.heapifyUp = index => {
let currentIndex = index,
parentIndex = this.parent(currentIndex);
while (currentIndex > 0 && this.heap[currentIndex] > this.heap[parentIndex]) {
this.swap(currentIndex, parentIndex);
currentIndex = parentIndex;
parentIndex = this.parent(parentIndex);
}
}
this.swap = (index1, index2) => {
[this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
}
this.print = () => {
return this.heap;
}
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,242 @@
---
id: 587d8251367417b2b2512c65
title: インデックスによってリンクリストから要素を削除する
challengeType: 1
forumTopicId: 301711
dashedName: remove-elements-from-a-linked-list-by-index
---
# --description--
別のデータ構造の話に移る前に、リンクリストを使って最後の練習をいくつか行いましょう。
与えられた `index` に位置している `element` を削除する `removeAt` メソッドを書きましょう。 メソッドは `removeAt(index)` と呼ばれる必要があります。 特定の `index` にある `element` を削除するには、リンクリストに沿って移動しながら各ノードの実行数を数え続ける必要があります。
リンクリストの要素に対して操作を繰り返すための一般的なテクニックは、比較対象ノードを「指し示す」ための <dfn>'runner'</dfn>、すなわち番兵を使用することです。 今回のケースでは、リストの `head` が出発点です。`0` で始まる `currentIndex` 変数で操作を開始します。 `currentIndex` は、ノードが 1 つ渡されるたびに 1 ずつ増加する必要があります。
[前回のレッスン](/learn/coding-interview-prep/data-structures/remove-elements-from-a-linked-list)で取り上げた `remove(element)` メソッドと同じように、`removeAt(index)` メソッドでノードを削除する際には、リストの残りの部分が孤立しないように注意する必要があります。 削除されたノードへの参照を持つノードに、次のノードへの参照を必ず持たせることにより、ノードの連続性を保ちます。
# --instructions--
与えられた `index` に位置しているノードを削除して返す、`removeAt(index)` メソッドを記述してください。 与えられた `index` が負の数であるか、リンクリストの `length` 以上である場合、このメソッドは `null` を返す必要があります。
**注:** `currentIndex` を数え続けることを忘れないでください。
# --hints--
`LinkedList` クラスに `removeAt` メソッドが必要です。
```js
assert(
(function () {
var test = new LinkedList();
return typeof test.removeAt === 'function';
})()
);
```
`removeAt` メソッドは、リンクリストの `length` を 1 減らす必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
test.removeAt(1);
return test.size() === 2;
})()
);
```
`removeAt` メソッドは、指定されたインデックスにある要素をリンクリストから削除する必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
test.add('bird');
test.removeAt(1);
return (
JSON.stringify(test.head()) ===
'{"element":"cat","next":{"element":"kitten","next":{"element":"bird","next":null}}}'
);
})()
);
```
リンクリストに要素が 1 つしかない場合、`removeAt` メソッドは、指定されたインデックスにある要素を削除して返し、リンクリストの長さを減らす必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
var removedItem = test.removeAt(0);
return test.head() === null && test.size() === 0 && removedItem === 'cat';
})()
);
```
`removeAt` メソッドは、削除されたノードの要素を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
return test.removeAt(1) === 'dog';
})()
);
```
与えられたインデックスが `0` より小さい場合、`removeAt` メソッドは `null` を返す必要があり、リンクリストを変更してはいけません。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
var removedItem = test.removeAt(-1);
return (
removedItem === null &&
JSON.stringify(test.head()) ===
'{"element":"cat","next":{"element":"dog","next":{"element":"kitten","next":null}}}'
);
})()
);
```
与えられたインデックスがリストの `length` 以上である場合、`removeAt` メソッドは `null` を返す必要があり、リンクリストを変更してはいけません。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
var removedItem = test.removeAt(3);
return (
removedItem === null &&
JSON.stringify(test.head()) ===
'{"element":"cat","next":{"element":"dog","next":{"element":"kitten","next":null}}}'
);
})()
);
```
# --seed--
## --seed-contents--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.size = function(){
return length;
};
this.head = function(){
return head;
};
this.add = function(element){
var node = new Node(element);
if(head === null){
head = node;
} else {
var currentNode = head;
while(currentNode.next){
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function (element) {
this.element = element;
this.next = null;
};
this.size = function () {
return length;
};
this.head = function () {
return head;
};
this.add = function (element) {
var node = new Node(element);
if (head === null) {
head = node;
} else {
var currentNode = head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
this.removeAt = function (index) {
var currentNode = head;
var previous = head;
var count = 0;
if (index >= length || index < 0) {
return null;
}
if (index === 0) {
var removed = head.element;
head = currentNode.next;
} else {
while (count < index) {
previous = currentNode;
currentNode = currentNode.next;
count++;
}
var removed = previous.next.element;
previous.next = currentNode.next;
}
length--;
return removed;
};
}
```

View File

@ -0,0 +1,210 @@
---
id: 587d8251367417b2b2512c63
title: リンクリストから要素を削除する
challengeType: 1
forumTopicId: 301712
dashedName: remove-elements-from-a-linked-list
---
# --description--
リンクリストの実装に不可欠な重要メソッドがもう一つあります。それは `remove` メソッドです。 このメソッドは、削除したい要素を引数として取り、リストを検索して、その要素が含まれているノードを見つけて削除します。
リンクリストからノードを削除するときは、削除によってそのリストの残りを誤って孤立させることがないように常に注意を払うことが重要です。 すべてのノードの `next` プロパティが、リスト内でそれに続くノードを指すということを思い出してください。 例えば、中央の要素を取り除く場合、その要素の前のノードの `next` プロパティから、その中央の要素の `next` プロパティ (リスト内の次のノード!) への接続を確保しなければなりません。
これはかなりややこしく聞こえるかもしれないので、分かりやすい概念モデルとしてにコンガラインの例に戻りましょう。 あなたがコンガラインの中にいて、すぐ前の人がラインを離れるところを想像してください。 ラインを離れたその人はもうラインの誰にも手を置いておらず、あなたは離れた人にもう手を置いていません。 あなたは前に進み、次に見える人に手を置きます。
削除したい要素が `head` 要素である場合、リンクリストの 2 つ目のノードに `head` を割り当てます。
# --instructions--
要素を受け取り、それをリンクリストから削除する `remove` メソッドを記述してください。
**注:** リストの `length` は、リンクリストから要素が削除されるたびに 1 ずつ減少する必要があります。
# --hints--
`LinkedList` クラスに `remove` メソッドが必要です。
```js
assert(
(function () {
var test = new LinkedList();
return typeof test.remove === 'function';
})()
);
```
`remove` メソッドは、最初のノードが削除されたときに、`head` を2 つ目のノードに再割り当てする必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.remove('cat');
return test.head().element === 'dog';
})()
);
```
`remove` メソッドは、ノードが 1 つ削除されるたびにリンクリストの `length` を 1 ずつ減らす必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('hamster');
test.remove('cat');
test.remove('fish');
return test.size() === 2;
})()
);
```
`remove` メソッドは、削除されたノードの前のノードの参照を、削除されたノードの `next` 参照に再割り当てする必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('snake');
test.add('kitten');
test.remove('snake');
return test.head().next.next.element === 'kitten';
})()
);
```
`remove` メソッドは、リンクリストに要素が存在しない場合にリンクリストを変更してはいけません。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
test.remove('elephant');
return (
JSON.stringify(test.head()) ===
'{"element":"cat","next":{"element":"dog","next":{"element":"kitten","next":null}}}'
);
})()
);
```
# --seed--
## --seed-contents--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.size = function(){
return length;
};
this.head = function(){
return head;
};
this.add = function(element){
var node = new Node(element);
if(head === null){
head = node;
} else {
var currentNode = head;
while(currentNode.next){
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
this.remove = function(element){
// Only change code below this line
// Only change code above this line
};
}
```
# --solutions--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.size = function(){
return length;
};
this.head = function(){
return head;
};
this.add = function(element){
var node = new Node(element);
if(head === null){
head = node;
} else {
var currentNode = head;
while(currentNode.next){
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
this.remove = function(element){
if (head === null) {
return;
}
var previous;
var currentNode = head;
while (currentNode.next !== null && currentNode.element !== element) {
previous = currentNode;
currentNode = currentNode.next;
}
if (currentNode.next === null && currentNode.element !== element) {
return;
}
else if (previous) {
previous.next = currentNode.next;
} else {
head = currentNode.next;
}
length--;
};
}
```

View File

@ -0,0 +1,67 @@
---
id: 587d8254367417b2b2512c71
title: ES6 でセットから要素を削除する
challengeType: 1
forumTopicId: 301713
dashedName: remove-items-from-a-set-in-es6
---
# --description--
`delete` メソッドを使って ES6 のセットから要素を削除する方法を練習しましょう。
まず、ES6のセットを作成します。
```js
var set = new Set([1,2,3]);
```
次に、`delete` メソッドを使用してセットから要素を削除します。
```js
set.delete(1);
console.log([...set]) // should return [ 2, 3 ]
```
# --instructions--
整数 1、2、3、4、5 を使ってセットを作成してください。
値 2 と 5 を削除してから、セットを返します。
# --hints--
セットには、値 1、3、4 が含まれている必要があります。
```js
assert(
(function () {
var test = checkSet();
return test.has(1) && test.has(3) && test.has(4) && test.size === 3;
})()
);
```
# --seed--
## --seed-contents--
```js
function checkSet(){
// Only change code below this line
var set = null;
// Only change code above this line
return set;
}
```
# --solutions--
```js
function checkSet(){
var set = new Set([1,2,3,4,5]);
set.delete(2);
set.delete(5);
return set;}
```

View File

@ -0,0 +1,205 @@
---
id: 587d825a367417b2b2512c88
title: 二重リンクリストを逆順にする
challengeType: 1
forumTopicId: 301714
dashedName: reverse-a-doubly-linked-list
---
# --description--
二重リンクリストに対して、通りがけ順にリストを逆にする reverse というメソッドを作りましょう。 このメソッドが実行されると、ヘッドは以前のテールを指し、テールは以前のヘッドを指します。 こうすると、ヘッドからテールまでリストを走査したときに、元のリストとは逆の順序でノードを訪問することになります。 空のリストを逆順にしようとすると、null が返される必要があります。
# --hints--
DoublyLinkedList データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
return typeof test == 'object';
})()
);
```
DoublyLinkedList に reverse というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
if (test.reverse == undefined) {
return false;
}
return typeof test.reverse == 'function';
})()
);
```
空のリストを逆順にすると、null が返される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
return test.reverse() == null;
})()
);
```
reverse メソッドはリストを逆順にする必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
test.add(58);
test.add(61);
test.add(32);
test.add(95);
test.add(41);
test.reverse();
return test.print().join('') == '4195326158';
})()
);
```
リストが逆順になったとき、次の参照と前の参照が正しく維持される必要があります。
```js
assert(
(function () {
var test = false;
if (typeof DoublyLinkedList !== 'undefined') {
test = new DoublyLinkedList();
}
test.add(11);
test.add(22);
test.add(33);
test.add(44);
test.add(55);
test.reverse();
return test.printReverse().join('') == '1122334455';
})()
);
```
# --seed--
## --after-user-code--
```js
DoublyLinkedList.prototype = Object.assign(
DoublyLinkedList.prototype,
{
add(data) {
if (this.head == null) {
this.head = new Node(data, null);
this.tail = this.head;
} else {
var node = this.head;
var prev = null;
while (node.next != null) {
prev = node;
node = node.next;
};
var newNode = new Node(data, node);
node.next = newNode;
this.tail = newNode;
};
},
print() {
if (this.head == null) {
return null;
} else {
var result = new Array();
var node = this.head;
while (node.next != null) {
result.push(node.data);
node = node.next;
};
result.push(node.data);
return result;
};
},
printReverse() {
if (this.tail == null) {
return null;
} else {
var result = new Array();
var node = this.tail;
while (node.prev != null) {
result.push(node.data);
node = node.prev;
};
result.push(node.data);
return result;
};
}
}
);
```
## --seed-contents--
```js
var Node = function(data, prev) {
this.data = data;
this.prev = prev;
this.next = null;
};
var DoublyLinkedList = function() {
this.head = null;
this.tail = null;
// Only change code below this line
// Only change code above this line
};
```
# --solutions--
```js
var Node = function(data, prev) {
this.data = data;
this.prev = prev;
this.next = null;
};
var DoublyLinkedList = function() {
this.head = null;
this.tail = null;
this.reverse = function() {
if (!this.head || !this.head.next) {
return this.head
}
let tail;
let temp;
let current = this.head;
while(current !== null) {
if(!tail) tail = current;
temp = current.prev;
current.prev = current.next;
current.next = temp;
current = current.prev;
}
this.head = temp.prev;
this.tail = tail
}
};
```

View File

@ -0,0 +1,293 @@
---
id: 587d8251367417b2b2512c64
title: リンクリスト内で検索する
challengeType: 1
forumTopicId: 301715
dashedName: search-within-a-linked-list
---
# --description--
作成したリンクリストクラスに、便利なメソッドをもう少し追加しましょう。 `Stack` クラスや `Queue` クラスと同じように、リストが空かどうかを知ることができたら便利ではありませんか?
リンクリスト内の特定の要素を見つけることもできるはずです。 データ構造の走査はたくさん練習しなければなりません! `element` を引数として取り、リンクリスト内におけるその要素の `index` を返す、`indexOf` メソッドを作成しましょう。 リンクリスト内にその要素が見つからない場合は、`-1` を返してください。
また、逆のことをする `elementAt` メソッドも実装しましょう。このメソッドは `index` を引数として取り、与えられた `index` にある `element` を返します。 `element` が見つからない場合は `undefined` を返します。
# --instructions--
リンクリストが空かどうかを調べる `isEmpty` メソッド、与えられた要素の `index` を返す `indexOf` メソッド、および、与えられた `index` にある `element` を返す `elementAt` メソッドを記述してください。
# --hints--
`LinkedList` クラスに `isEmpty` メソッドが必要です。
```js
assert(
(function () {
var test = new LinkedList();
return typeof test.isEmpty === 'function';
})()
);
```
リンクリストに 1 つ以上の要素がある場合、`isEmpty` メソッドは `false` を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
return test.isEmpty() === false;
})()
);
```
リンクリストに要素がない場合、`isEmpty` メソッドは `true` を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
return test.isEmpty() === true;
})()
);
```
`LinkedList` クラスに `indexOf` メソッドが必要です。
```js
assert(
(function () {
var test = new LinkedList();
return typeof test.indexOf === 'function';
})()
);
```
`indexOf` メソッドは、リンクリスト内で見つかった、与えられた要素のインデックスを返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
return test.indexOf('cat') === 0;
})()
);
```
与えられた要素がリンクリスト内に見つからない場合、`indexOf` メソッドは `-1` を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
return test.indexOf('pony') === -1;
})()
);
```
`LinkedList` クラスに `elementAt` メソッドが必要です。
```js
assert(
(function () {
var test = new LinkedList();
return typeof test.elementAt === 'function';
})()
);
```
`elementAt` メソッドは、リンクリスト内の与えられたインデックスで見つかった要素を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
return test.elementAt(1) === 'dog';
})()
);
```
`elementAt` メソッドは、リンクリスト内の与えられたインデックスに、与えられた要素が見つからない場合、`undefined` を返す必要があります。
```js
assert(
(function () {
var test = new LinkedList();
test.add('cat');
test.add('dog');
test.add('kitten');
return test.elementAt(5) === undefined;
})()
);
```
# --seed--
## --seed-contents--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.size = function() {
return length;
};
this.head = function(){
return head;
};
this.add = function(element){
var node = new Node(element);
if(head === null){
head = node;
} else {
var currentNode = head;
while(currentNode.next){
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
this.remove = function(element){
var currentNode = head;
var previousNode;
if(currentNode.element === element){
head = currentNode.next;
} else {
while(currentNode.element !== element) {
previousNode = currentNode;
currentNode = currentNode.next;
}
previousNode.next = currentNode.next;
}
length --;
};
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function LinkedList() {
var length = 0;
var head = null;
var Node = function(element){
this.element = element;
this.next = null;
};
this.size = function() {
return length;
};
this.head = function(){
return head;
};
this.add = function(element){
var node = new Node(element);
if(head === null){
head = node;
} else {
var currentNode = head;
while(currentNode.next){
currentNode = currentNode.next;
}
currentNode.next = node;
}
length++;
};
this.remove = function(element){
var currentNode = head;
var previousNode;
if(currentNode.element === element){
head = currentNode.next;
} else {
while(currentNode.element !== element) {
previousNode = currentNode;
currentNode = currentNode.next;
}
previousNode.next = currentNode.next;
}
length --;
};
this.indexOf = function(element) {
if (head === null) return -1
let current = head;
let index = 0;
while (current.element !== element && current.next !== null) {
current = current.next;
index++
}
if (current.element !== element && current.next === null) {
return -1
}
return index;
}
this.elementAt = function(index) {
if (head === null) return undefined;
let current = head;
let currentIndex = 0;
while (currentIndex !== index && current.next !== null) {
current = current.next;
currentIndex++
}
if (currentIndex !== index && current.next === null) {
return undefined;
}
return current.element;
}
this.isEmpty = function() {
return length === 0;
}
}
```

View File

@ -0,0 +1,94 @@
---
id: 587d8253367417b2b2512c6a
title: 型付き配列
challengeType: 1
forumTopicId: 301716
dashedName: typed-arrays
---
# --description--
配列は、さまざまな要素を大量に保持できる JavaScript オブジェクトです。
```js
var complexArr = [1, 5, "2", "Word", {"name": "James"}];
```
バックグラウンドで行われることは、基本的に、ブラウザがその配列に対して適切なメモリ空間を自動的に与えることです。 データの追加や削除を行ったときも、必要に応じてメモリ空間が変化します。
しかし、高いパフォーマンスと多様な要素型が求められる世界では、配列に与えるメモリの量をより具体的に指定しなければならない場合があります。
それを可能にするのが<dfn>型付き配列</dfn> です。 これで、配列に与えるメモリの量を指定できるようになります。 利用可能な配列型の基本概要と、その配列に含まれる各要素のサイズ (バイト数) は次の通りです。
<table class='table table-striped'><tbody><tr><th></th><th>各要素のサイズ (バイト数)</th></tr><tr><td><code>Int8Array</code></td><td>1</td></tr><tr><td><code>Uint8Array</code></td><td>1</td></tr><tr><td><code>Uint8ClampedArray</code></td><td>1</td></tr><tr><td><code>Int16Array</code></td><td>2</td></tr><tr><td><code>Uint16Array</code></td><td>2</td></tr><tr><td><code>Int32Array</code></td><td>4</td></tr><tr><td><code>Uint32Array</code></td><td>4</td></tr><tr><td><code>Float32Array</code></td><td>4</td></tr><tr><td><code>Float64Array</code></td><td>8</td></tr></tbody></table>
これらのような配列を作る方法は 2 つあります。 方法の一つは、配列を直接作成することです。 長さ 3 の `Int16Array` を作成するには、次のようにします。
```js
var i8 = new Int16Array(3);
console.log(i8);
// Returns [0, 0, 0]
```
また、<dfn>バッファ</dfn>を作成して、配列が受け取るデータ量 (バイト数) を割り当てることもできます。 **注**
バッファを使って型付き配列を作成するには、割り当てるバイト数を、上に示したバイト数の倍数にする必要があります。
```js
// Create same Int16Array array differently
var byteSize = 6; // Needs to be multiple of 2
var buffer = new ArrayBuffer(byteSize);
var i8View = new Int16Array(buffer);
buffer.byteLength; // Returns 6
i8View.byteLength; // Returns 6
console.log(i8View); // Returns [0, 0, 0]
```
<dfn>バッファ</dfn>は、データを保持するだけの汎用オブジェクトです。 通常、バッファにアクセスすることはできません。 アクセスするには、先に<dfn>ビュー</dfn>を作成する必要があります。
```js
i8View[0] = 42;
console.log(i8View); // Returns [42, 0, 0]
```
**注**
型付き配列には、普通の配列が持つメソッドの一部、例えば `.pop()``.push()` がありません。 また、型付き配列では、対象物が配列であるかを調べる `Array.isArray()` が失敗します。 この配列は比較的単純ですが、そのことは、旧来の JavaScript エンジンに実装する際の長所になり得ます。
# --instructions--
最初に 64 バイトの `buffer` を作成してください。 次に、`i32View` と呼ばれるビューを持つ `Int32Array` 型の配列を作成してください。
# --hints--
`buffer` のサイズを 64 バイトにする必要があります。
```js
assert(buffer.byteLength === 64);
```
バッファの `i32View` ビューのサイズを 64 バイトにする必要があります。
```js
assert(i32View.byteLength === 64);
```
バッファの `i32View` ビューの長さを 16 要素にする必要があります。
```js
assert(i32View.length === 16);
```
# --seed--
## --seed-contents--
```js
var buffer;
var i32View;
```
# --solutions--
```js
var buffer = new ArrayBuffer(64);
var i32View = new Int32Array(buffer);
```

View File

@ -0,0 +1,73 @@
---
id: 587d8255367417b2b2512c72
title: ES6 Set に .has と .size を使用する
challengeType: 1
forumTopicId: 301717
dashedName: use--has-and--size-on-an-es6-set
---
# --description--
ES6 Set オブジェクトで利用できる .has メソッドと .size メソッドを見てみましょう。
まず、ES6 Set を作成します。
```js
var set = new Set([1,2,3]);
```
.has メソッドは、その値がセットに含まれているかどうかを調べます。
```js
var hasTwo = set.has(2);
```
.size メソッドは、セットのサイズを表す整数を返します。
```js
var howBig = set.size;
```
# --instructions--
この課題では、checkSet() 関数に配列と値を渡します。 この関数は配列引数から ES6 Set を作成します。 値の引数がセットに含まれているかどうかを調べてください。 セットのサイズを求めてください。 そして、配列内のこれら 2 つの値を返してください。
# --hints--
`checkSet([4, 5, 6], 3)` は [false, 3 ] を返す必要があります
```js
assert(
(function () {
var test = checkSet([4, 5, 6], 3);
return DeepEqual(test, [false, 3]);
})()
);
```
# --seed--
## --seed-contents--
```js
function checkSet(arrToBeSet, checkValue){
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function checkSet(arrToBeSet, checkValue){
var set = new Set(arrToBeSet);
var result = [
set.has(checkValue),
set.size
];
return result;
}
```

View File

@ -0,0 +1,261 @@
---
id: 587d8258367417b2b2512c7f
title: 二分探索木に幅優先探索を使用する
challengeType: 1
forumTopicId: 301718
dashedName: use-breadth-first-search-in-a-binary-search-tree
---
# --description--
ここでは、木を走査するもう一つの方法である幅優先探索について説明します。 直前のチャレンジで学んだ深さ優先探索とは対照的に、幅優先探索は、次のレベルに進む前に、木の中において与えられたレベルに位置するノードをすべて探索します。 一般に、幅優先探索アルゴリズムの設計において、ヘルパーデータ構造としてキューが利用されます。
このメソッドでは、まず、キューに根ノードを追加します。 次に、キューの先頭要素をキューから取り出す操作のループを開始し、それを新しい配列に追加し、次に、その要素の子部分木を両方とも調べます。 子が null でない場合、それぞれがキューに追加されます。 このプロセスはキューが空になるまで続きます。
# --instructions--
`levelOrder` という名前の木に幅優先探索メソッドを作成しましょう。 このメソッドは、幅優先方式で探索された、すべての木ノードの値が含まれている配列を返す必要があります。 ノード自体ではなく、配列の値を返すようにしてください。 各レベルは左から右へ走査される必要があります。 次に、これに似た `reverseLevelOrder` と呼ばれるメソッドを書きましょう。このメソッドは同じ探索を行いますが、各レベルでの方向が逆 (右から左) になります。
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `levelOrder` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.levelOrder == 'function';
})()
);
```
二分探索木に `reverseLevelOrder` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.reverseLevelOrder == 'function';
})()
);
```
`levelOrder` メソッドは、レベル順に探索された木ノード値の配列を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.levelOrder !== 'function') {
return false;
}
test.add(7);
test.add(1);
test.add(9);
test.add(0);
test.add(3);
test.add(8);
test.add(10);
test.add(2);
test.add(5);
test.add(4);
test.add(6);
return test.levelOrder().join('') == '719038102546';
})()
);
```
`reverseLevelOrder` メソッドは、レベル順の逆順に探索された木ノード値の配列を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.reverseLevelOrder !== 'function') {
return false;
}
test.add(7);
test.add(1);
test.add(9);
test.add(0);
test.add(3);
test.add(8);
test.add(10);
test.add(2);
test.add(5);
test.add(4);
test.add(6);
return test.reverseLevelOrder().join('') == '791108305264';
})()
);
```
`levelOrder` メソッドは、空の木の場合に `null` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.levelOrder !== 'function') {
return false;
}
return test.levelOrder() == null;
})()
);
```
`reverseLevelOrder` メソッドは、空の木の場合に `null` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.reverseLevelOrder !== 'function') {
return false;
}
return test.reverseLevelOrder() == null;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
return searchTree(node);
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
this.levelOrder = (root = this.root) => {
if(!root) return null;
let queue = [root];
let results = [];
while(queue.length > 0) {
let node = queue.shift();
results.push(node.value);
if(node.left) queue.push(node.left);
if(node.right) queue.push(node.right);
}
return results;
}
this.reverseLevelOrder = (root = this.root) => {
if(!root) return null;
let queue = [root];
let results = [] ;
while ( queue.length > 0) {
let node = queue.shift();
results.push(node.value);
if(node.right) queue.push(node.right);
if(node.left ) queue.push(node.left);
}
return results;
}
// Only change code above this line
}
```

View File

@ -0,0 +1,328 @@
---
id: 587d8257367417b2b2512c7e
title: 二分探索木で深さ優先探索を使用する
challengeType: 1
forumTopicId: 301719
dashedName: use-depth-first-search-in-a-binary-search-tree
---
# --description--
二分探索木で特定の値を検索する方法は既に学びました。 しかし、木全体を探索したい場合はどうすれば良いでしょうか? あるいは、順序付きの木がないときに、単に値を検索したい場合はどうでしょうか? ここでは、ツリーデータ構造を探索するために木を走査する方法をいくつか紹介します。 1 つ目は深さ優先探索です。 深さ優先探索は、探索が別の部分木に移る前に、与えられた部分木をできるだけ深く探索します。 これを行うには次の 3 つの方法があります。通りがけ順: 左端のノードで探索を開始し、右端のノードで終了します。 行きがけ順: 葉より先にすべての根を探索します。 帰りがけ順: 根より先にすべての葉を探索します。 お察しの通り、木がどのような種類のデータを格納しているか、そして何を探したいかに応じて、異なる検索方法を選択できます。 二分探索木の場合、通りがけ順走査は、ソートされた順序でノードを返します。
# --instructions--
ここでは、二分探索木に対してこれら 3 つの探索方法を作成します。 深さ優先探索は、子ノードが存在する限りさらに部分木の探索を続けるという、本質的に再帰性を持つ操作です。 この基本概念を理解したら、ノードと部分木の探索順序を変えるだけで上述の 3 つの探索をすべて作成できます。 例えば帰りがけ順の探索では、ノード自体を返し始める前に、葉ノードまでの全体を再帰的に探索します。一方、行きがけ順の探索では、最初にノードを返してから、木の下の方へ再帰的に探索し続けます。 この木に `inorder``preorder``postorder` の各メソッドを定義してください。 これらの各メソッドは、木の走査を表す要素の配列を返す必要があります。 ノード自体ではなく、配列内の各ノードの整数値を返すようにしてください。 最後に、木が空の場合は `null` を返してください。
# --hints--
`BinarySearchTree` データ構造が存在する必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
}
return typeof test == 'object';
})()
);
```
二分探索木に `inorder` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.inorder == 'function';
})()
);
```
二分探索木に `preorder` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.preorder == 'function';
})()
);
```
二分探索木に `postorder` というメソッドが必要です。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
return typeof test.postorder == 'function';
})()
);
```
`inorder` メソッドは、通りがけ順走査によって得たノード値の配列を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.inorder !== 'function') {
return false;
}
test.add(7);
test.add(1);
test.add(9);
test.add(0);
test.add(3);
test.add(8);
test.add(10);
test.add(2);
test.add(5);
test.add(4);
test.add(6);
return test.inorder().join('') == '012345678910';
})()
);
```
`preorder` メソッドは、行きがけ順走査によって得たノード値の配列を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.preorder !== 'function') {
return false;
}
test.add(7);
test.add(1);
test.add(9);
test.add(0);
test.add(3);
test.add(8);
test.add(10);
test.add(2);
test.add(5);
test.add(4);
test.add(6);
return test.preorder().join('') == '710325469810';
})()
);
```
`postorder` メソッドは、帰りがけ順走査によって得たノード値の配列を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.postorder !== 'function') {
return false;
}
test.add(7);
test.add(1);
test.add(9);
test.add(0);
test.add(3);
test.add(8);
test.add(10);
test.add(2);
test.add(5);
test.add(4);
test.add(6);
return test.postorder().join('') == '024653181097';
})()
);
```
`inorder` メソッドは、空の木の場合に `null` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.inorder !== 'function') {
return false;
}
return test.inorder() == null;
})()
);
```
`preorder` メソッドは、空の木の場合に `null` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.preorder !== 'function') {
return false;
}
return test.preorder() == null;
})()
);
```
`postorder` メソッドは、空の木の場合に `null` を返す必要があります。
```js
assert(
(function () {
var test = false;
if (typeof BinarySearchTree !== 'undefined') {
test = new BinarySearchTree();
} else {
return false;
}
if (typeof test.postorder !== 'function') {
return false;
}
return test.postorder() == null;
})()
);
```
# --seed--
## --after-user-code--
```js
BinarySearchTree.prototype = Object.assign(
BinarySearchTree.prototype,
{
add: function(value) {
function searchTree(node) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else if (node.left != null) {
return searchTree(node.left);
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
return;
} else if (node.right != null) {
return searchTree(node.right);
}
} else {
return null;
}
}
var node = this.root;
if (node == null) {
this.root = new Node(value);
return;
} else {
return searchTree(node);
}
}
}
);
```
## --seed-contents--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.result = [];
this.inorder = function(node) {
if (!node) node = this.root;
if (!node) return null;
if (node.left) this.inorder(node.left);
this.result.push(node.value);
if (node.right) this.inorder(node.right);
return this.result;
};
this.preorder = function(node) {
if (!node) node = this.root;
if (!node) return null;
this.result.push(node.value);
if (node.left) this.preorder(node.left);
if (node.right) this.preorder(node.right);
return this.result;
};
this.postorder = function(node) {
if (!node) node = this.root;
if (!node) return null;
if (node.left) this.postorder(node.left);
if (node.right) this.postorder(node.right);
this.result.push(node.value);
return this.result;
};
}
```

View File

@ -0,0 +1,59 @@
---
id: 587d8255367417b2b2512c73
title: ES5 Set() 統合にスプレッドとノートを使用する
challengeType: 1
forumTopicId: 301720
dashedName: use-spread-and-notes-for-es5-set-integration
---
# --description--
ES6 スプレッド演算子 "`...`" を覚えていますか?
"`...`" は、ES6 の反復可能なオブジェクトを配列に変換することができます。
Set を作成し、スプレッド機能を使ってみましょう。
```js
var set = new Set([1,2,3]);
var setToArr = [...set]
console.log(setToArr) // returns [ 1, 2, 3 ]
```
# --instructions--
この課題では、Set オブジェクトを `checkSet` 関数に渡します。 この関数は、Set の値が含まれている配列を返す必要があります。
これで、ES6 `Set()` オブジェクトの使い方を正しく学びました。よくできました!
# --hints--
`checkSet(new Set([1,2,3,4,5,6,7])``[1, 2, 3, 4, 5, 6, 7]` を返す必要があります。
```js
assert(
(function () {
var test = checkSet(new Set([1, 2, 3, 4, 5, 6, 7]));
return DeepEqual(test, [1, 2, 3, 4, 5, 6, 7]);
})()
);
```
# --seed--
## --seed-contents--
```js
function checkSet(set){
// Only change code below this line
// Only change code above this line
}
```
# --solutions--
```js
function checkSet(set){
return [...set];}
```

View File

@ -0,0 +1,55 @@
---
id: 587d8251367417b2b2512c61
title: リンクリスト内のノードを操作する
challengeType: 1
forumTopicId: 301721
dashedName: work-with-nodes-in-a-linked-list
---
# --description--
コンピュータサイエンスの世界でよく目にするもう一つのデータ構造は、<dfn>リンクリスト</dfn>です。 リンクリストは「ノード」と呼ばれるデータ要素の線形コレクションであり、それぞれが次の要素を指しています。 Each <dfn>node</dfn> in a linked list contains two key pieces of information: the `element` itself, and a reference to the next `node`.
あなたがコンガラインの中にいるのを想像してみてください。 あなたはラインの中で自分のすぐ前の人に手を置き、後ろの人はあなたに手を置いています。 前の人はあなたの正面にいますが、その人が視界を遮るため、もっと前にいる人たちがあなたからは見えません。 ノードはコンガラインの人と同じようなものです。自分のことを知っていて、目の前にいる人だけを見ています。その人の前や自分の後ろにいる、他の人たちの存在には気付きません。
# --instructions--
コードエディターに、`Kitten``Puppy` という 2 つのノードが既に作成され、`Kitten` ノードが `Puppy` ノードに手動で接続されています。
`Cat``Dog` ノードを作成し、それらを手動でラインに追加してください。
# --hints--
`Puppy` ノードは `Cat` ノードへの参照を持つ必要があります。
```js
assert(Puppy.next.element === 'Cat');
```
`Cat` ノードは `Dog` ノードへの参照を持つ必要があります。
```js
assert(Cat.next.element === 'Dog');
```
# --seed--
## --seed-contents--
```js
var Node = function(element) {
this.element = element;
this.next = null;
};
var Kitten = new Node('Kitten');
var Puppy = new Node('Puppy');
Kitten.next = Puppy;
// Only change code below this line
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,73 @@
---
id: 5900f36e1000cf542c50fe80
title: '問題 1: 3 と 5 の倍数'
challengeType: 5
forumTopicId: 301722
dashedName: problem-1-multiples-of-3-and-5
---
# --description--
3 または 5 の倍数である 10 未満の自然数をすべて並べると、3, 5, 6, 9 になります。 これらの倍数の和は 23 です。
与えられたパラメータ値 `number` 未満である、3 または 5 の倍数の総和を求めなさい。
# --hints--
`multiplesOf3and5(10)` は数値を返す必要があります。
```js
assert(typeof multiplesOf3and5(10) === 'number');
```
`multiplesOf3and5(49)` は 543 を返す必要があります。
```js
assert.strictEqual(multiplesOf3and5(49), 543);
```
`multiplesOf3and5(1000)` は 233168 を返す必要があります。
```js
assert.strictEqual(multiplesOf3and5(1000), 233168);
```
`multiplesOf3and5(8456)` は 16687353 を返す必要があります。
```js
assert.strictEqual(multiplesOf3and5(8456), 16687353);
```
`multiplesOf3and5(19564)` は 89301183 を返す必要があります。
```js
assert.strictEqual(multiplesOf3and5(19564), 89301183);
```
# --seed--
## --seed-contents--
```js
function multiplesOf3and5(number) {
return true;
}
multiplesOf3and5(1000);
```
# --solutions--
```js
const multiplesOf3and5 = (number) => {
var total = 0;
for(var i = 0; i < number; i++) {
if(i % 3 == 0 || i % 5 == 0) {
total += i;
}
}
return total;
};
```

View File

@ -0,0 +1,81 @@
---
id: 5900f3761000cf542c50fe89
title: '問題 10: 素数の和'
challengeType: 5
forumTopicId: 301723
dashedName: problem-10-summation-of-primes
---
# --description--
10 より小さい素数の和は、2 + 3 + 5 + 7 = 17 です。
`n` より小さい素数の総和を求めなさい。
# --hints--
`primeSummation(17)` は数値を返す必要があります。
```js
assert(typeof primeSummation(17) === 'number');
```
`primeSummation(17)` は 41 を返す必要があります。
```js
assert.strictEqual(primeSummation(17), 41);
```
`primeSummation(2001)` は 277050 を返す必要があります。
```js
assert.strictEqual(primeSummation(2001), 277050);
```
`primeSummation(140759)` は 873608362 を返す必要があります。
```js
assert.strictEqual(primeSummation(140759), 873608362);
```
`primeSummation(2000000)` は 142913828922 を返す必要があります。
```js
assert.strictEqual(primeSummation(2000000), 142913828922);
```
# --seed--
## --seed-contents--
```js
function primeSummation(n) {
return true;
}
primeSummation(2000000);
```
# --solutions--
```js
function primeSummation(n) {
if (n < 3) { return 0 };
let nums = [0, 0, 2];
for (let i = 3; i < n; i += 2){
nums.push(i);
nums.push(0);
}
let sum = 2;
for (let i = 3; i < n; i += 2){
if (nums[i] !== 0){
sum += nums[i];
for (let j = i*i; j < n; j += i){
nums[j] = 0;
}
}
}
return sum;
}
```

View File

@ -0,0 +1,87 @@
---
id: 5900f3d01000cf542c50fee3
title: '問題 100: 調整された確率'
challengeType: 5
forumTopicId: 301724
dashedName: problem-100-arranged-probability
---
# --description--
箱の中に、15 枚の青い円盤と 6 枚の赤い円盤、計 21 枚の色付き円盤が入っています。2 枚の円盤を無作為に取り出したときにそれが青い円盤 2 枚である確率は、次のように求めることができます。
$${P(BB)} = \frac{15}{21}×\frac{14}{20} = \frac{1}{2}$$
無作為に取り出した 2 枚が青い円盤である確率がちょうど 50% になるように調整した場合、枚数が次に多いのは、85 枚の青い円盤と 35 枚の赤い円盤が入った箱です。
合計枚数が `limit` より多くなる最初の調整方法を見つけ、その箱に入っている青い円盤の枚数を求めなさい。
# --hints--
`arrangedProbability(20)` は数値を返す必要があります。
```js
assert(typeof arrangedProbability(10) === 'number');
```
`arrangedProbability(20)``15` を返す必要があります。
```js
assert.strictEqual(arrangedProbability(20), 15);
```
`arrangedProbability(100)``85` を返す必要があります。
```js
assert.strictEqual(arrangedProbability(100), 85);
```
`arrangedProbability(100000)``97513` を返す必要があります。
```js
assert.strictEqual(arrangedProbability(100000), 97513);
```
`arrangedProbability(1000000000)``3822685023` を返す必要があります。
```js
assert.strictEqual(arrangedProbability(1000000000), 3822685023);
```
`arrangedProbability(1000000000000)``756872327473` を返す必要があります。
```js
assert.strictEqual(arrangedProbability(1000000000000), 756872327473);
```
# --seed--
## --seed-contents--
```js
function arrangedProbability(limit) {
return true;
}
arrangedProbability(20);
```
# --solutions--
```js
function arrangedProbability(limit) {
// Based on https://www.mathblog.dk/project-euler-100-blue-discs-two-blue/
let blue = 15;
let discs = 21;
while (discs < limit) {
const nextBlue = 3 * blue + 2 * discs - 2;
const nextDiscs = 4 * blue + 3 * discs - 3;
blue = nextBlue;
discs = nextDiscs;
}
return blue;
}
```

View File

@ -0,0 +1,56 @@
---
id: 5900f3d21000cf542c50fee4
title: '問題 101: 最適な多項式'
challengeType: 5
forumTopicId: 301725
dashedName: problem-101-optimum-polynomial
---
# --description--
数列の先頭から k 個の項が提示されたときに、次の項の値を確実に知ることは不可能です。その数列をモデル化できる多項式関数が無限にあるからです。
例として、平方数の数列を考えます。 これは生成関数 $u_n = n^3: 1, 8, 27, 64, 125, 216, \ldots$ によって定義されます。
この数列の最初の 2 項だけが与えられたとします。 「シンプル・イズ・ベスト」の原則に基づき、線形関係があると想定して次の項が 15 であると予想します (公差 7)。 最初の 3 項が提示されたとしても、上と同じ原則により二次関係があると想定します。
ここでは、数列の先頭から第 k 項までに対する最適な多項式生成関数の第 $n$ 項を $OP(k, n)$ とします。 $n ≤ k$ のとき、$OP(k, n)$ がその数列の項を正確に生成することは明らかでしょう。そしておそらく、FIT (First Incorrect Term = 最初の不正な項) は $OP(k, k+1)$ でしょう。この場合、これを BOP (Bad OP = 不良 OP) と呼ぶことにします。
原則として、配列の最初の項のみが与えられた場合、それは定数であると仮定することが最も理にかなうと考えられます。すなわち、$n ≥ 2, OP(1, n) = u_1$ です。
したがって、立方数の数列について次の OP が得られます。
$$\begin{array}{ll} OP(1, n) = 1 & 1, {\color{red}1}, 1, 1, \ldots \\\\ OP(2, n) = 7n6 & 1, 8, {\color{red}{15}}, \ldots \\\\ OP(3, n) = 6n^211n+6 & 1, 8, 27, {\color{red}{58}}, \ldots \\\\ OP(4, n) = n^3 & 1, 8, 27, 64, 125, \ldots \end{array}$$
明らかに、k ≥ 4 に対して BOP は存在しません。 BOP によって生成された FIT の和 (上では $\color{red}{red}$ で示されています) は、1 + 15 + 58 = 74 となります。 次の 10 次多項式生成関数を考えます。
$$u_n = 1 n + n^2 n^3 + n^4 n^5 + n^6 n^7 + n^8 n^9 + n^{10}$$
BOP の FIT の和を求めなさい。
# --hints--
`optimumPolynomial()``37076114526` を返す必要があります。
```js
assert.strictEqual(optimumPolynomial(), 37076114526);
```
# --seed--
## --seed-contents--
```js
function optimumPolynomial() {
return true;
}
optimumPolynomial();
```
# --solutions--
```js
// solution required
```

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,53 @@
---
id: 5900f3d61000cf542c50fee7
title: '問題 103: 特殊和部分集合: 最適'
challengeType: 5
forumTopicId: 301727
dashedName: problem-103-special-subset-sums-optimum
---
# --description--
大きさが n である集合 A の要素の和を、$S(A)$ で表します。 空でなく互いに素な 2 つの部分集合 B と C について、次の性質が真の場合、それを「特殊和集合」と呼ぶことにします。
1. $S(B) ≠ S(C)$ である。すなわち、部分集合の和が等しくてはならない。
2. B が C より多くの要素を含む場合、$S(B) > S(C)$ である。
与えられた n に対して $S(A)$ が最小化されている集合を、「最適な特殊和集合」と呼ぶことにします。 最初の 5 つの最適な特殊和集合は次のとおりです。
$$\begin{align} & n = 1: \\{1\\} \\\\ & n = 2: \\{1, 2\\} \\\\ & n = 3: \\{2, 3, 4\\} \\\\ & n = 4: \\{3, 5, 6, 7\\} \\\\ & n = 5: \\{6, 9, 11, 12, 13\\} \\\\ \end{align}$$
与えられた最適な集合 $A = \\{a_1, a_2, \ldots, a_n\\}$ に対して、次に出現する最適な集合は $B = \\{b, a_1 + b, a_2 + b, \ldots, a_n + b\\}$ であり、ここで、b は前行の「途中の」要素です。
この「ルール」を適用すると、$n = 6$ に対する最適な集合として予想されるのは $A = \\{11, 17, 20, 22, 23, 24\\}$ ($S(A) = 117$) です。 しかし、最適に近い集合を得るためのアルゴリズムを適用しただけなので、これは最適な集合ではありません。 $n = 6$ に対する最適な集合は $A = \\{11, 18, 19, 20, 22, 25\\}$, $S(A) = 115$ であり、これに対応する集合文字列は `111819202225` です。
A が $n = 7$ に対する最適な特殊和集合であると仮定し、その集合文字列を求めなさい。
**注:** この問題は、問題 105 および問題 106 と関連しています。
# --hints--
`optimumSpecialSumSet()` は文字列 `20313839404245` を返す必要があります。
```js
assert.strictEqual(optimumSpecialSumSet(), '20313839404245');
```
# --seed--
## --seed-contents--
```js
function optimumSpecialSumSet() {
return true;
}
optimumSpecialSumSet();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3d51000cf542c50fee6
title: '問題 104: 両端がパンデジタルであるフィボナッチ数'
challengeType: 5
forumTopicId: 301728
dashedName: problem-104-pandigital-fibonacci-ends
---
# --description--
フィボナッチ数列は次の漸化関係によって定義されます。
$F_n = F_{n 1} + F_{n 2}$ ここで、$F_1 = 1$, $F_2 = 1$
これにより、113 桁の $F_{541}$は、下位 9 桁が 1 から 9 のパンデジタル数 (1 から 9 のすべての数字を含むが、必ずしもその順序ではない) になる初めてのフィボナッチ数であることがわかります。 そして 575 桁の $F_{2749}$ は、上位 9 桁が 1 から 9 のパンデジタル数字である、最初のフィボナッチ数です。
上位 9 桁と下位 9 桁の両方が 1 から 9 のパンデジタル数であるような初めてのフィボナッチ数を $F_k$ とし、`k` を求めなさい。
# --hints--
`pandigitalFibonacciEnds()``329468` を返す必要があります。
```js
assert.strictEqual(pandigitalFibonacciEnds(), 329468);
```
# --seed--
## --seed-contents--
```js
function pandigitalFibonacciEnds() {
return true;
}
pandigitalFibonacciEnds();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,59 @@
---
id: 5900f3d61000cf542c50fee8
title: '問題 105: 特殊和集合: 検証'
challengeType: 5
forumTopicId: 301729
dashedName: problem-105-special-subset-sums-testing
---
# --description--
大きさが n である集合 A の要素の和を、$S(A)$ で表します。 空でなく互いに素な 2 つの部分集合 B と C について、次の性質が真の場合、それを「特殊和集合」と呼ぶことにします。
1. $S(B) ≠ S(C)$ である。すなわち、部分集合の和が等しくてはならない。
2. B が C より多くの要素を含む場合、$S(B) > S(C)$ である。
例えば、{81, 88, 75, 42, 87, 84, 86, 65} は、65 + 87 + 88 = 75 + 81 + 84 なので特殊和集合ではありません。一方、{157, 150, 164, 119, 79, 159, 161, 139, 158} は、考えられるすべての部分集合ペアの組み合わせの両ルールを満たし、$S(A) = 1286$ です。
7 個から 12 個の要素からなる集合が 100 個含まれている配列 `sets` を使用して (上の 2 例はこの配列に含まれる最初の 2 つの集合)、特殊和集合 $A_1, A_2, \ldots, A_k$ をすべて見つけ、$(A_1) + S(A_2) + \cdots + S(A_k)$ の値を求めなさい。
**注:** この問題は、問題 103 および問題 106 と関連しています。
# --hints--
`testingSpecialSubsetSums(testSets)``73702` を返す必要があります。
```js
assert.strictEqual(testingSpecialSubsetSums(_testSets), 73702);
```
# --seed--
## --after-user-code--
```js
const _testSets = [
[81,88,75,42,87,84,86,65],[157,150,164,119,79,159,161,139,158],[673,465,569,603,629,592,584,300,601,599,600],[90,85,83,84,65,87,76,46],[165,168,169,190,162,85,176,167,127],[224,275,278,249,277,279,289,295,139],[354,370,362,384,359,324,360,180,350,270],[599,595,557,298,448,596,577,667,597,588,602],[175,199,137,88,187,173,168,171,174],[93,187,196,144,185,178,186,202,182],[157,155,81,158,119,176,152,167,159],[184,165,159,166,163,167,174,124,83],[1211,1212,1287,605,1208,1189,1060,1216,1243,1200,908,1210],[339,299,153,305,282,304,313,306,302,228],[94,104,63,112,80,84,93,96],[41,88,82,85,61,74,83,81],[90,67,84,83,82,97,86,41],[299,303,151,301,291,302,307,377,333,280],[55,40,48,44,25,42,41],[1038,1188,1255,1184,594,890,1173,1151,1186,1203,1187,1195],[76,132,133,144,135,99,128,154],[77,46,108,81,85,84,93,83],[624,596,391,605,529,610,607,568,604,603,453],[83,167,166,189,163,174,160,165,133],[308,281,389,292,346,303,302,304,300,173],[593,1151,1187,1184,890,1040,1173,1186,1195,1255,1188,1203],[68,46,64,33,60,58,65],[65,43,88,87,86,99,93,90],[83,78,107,48,84,87,96,85],[1188,1173,1256,1038,1187,1151,890,1186,1184,1203,594,1195],[302,324,280,296,294,160,367,298,264,299],[521,760,682,687,646,664,342,698,692,686,672],[56,95,86,97,96,89,108,120],[344,356,262,343,340,382,337,175,361,330],[47,44,42,27,41,40,37],[139,155,161,158,118,166,154,156,78],[118,157,164,158,161,79,139,150,159],[299,292,371,150,300,301,281,303,306,262],[85,77,86,84,44,88,91,67],[88,85,84,44,65,91,76,86],[138,141,127,96,136,154,135,76],[292,308,302,346,300,324,304,305,238,166],[354,342,341,257,348,343,345,321,170,301],[84,178,168,167,131,170,193,166,162],[686,701,706,673,694,687,652,343,683,606,518],[295,293,301,367,296,279,297,263,323,159],[1038,1184,593,890,1188,1173,1187,1186,1195,1150,1203,1255],[343,364,388,402,191,383,382,385,288,374],[1187,1036,1183,591,1184,1175,888,1197,1182,1219,1115,1167],[151,291,307,303,345,238,299,323,301,302],[140,151,143,138,99,69,131,137],[29,44,42,59,41,36,40],[348,329,343,344,338,315,169,359,375,271],[48,39,34,37,50,40,41],[593,445,595,558,662,602,591,297,610,580,594],[686,651,681,342,541,687,691,707,604,675,699],[180,99,189,166,194,188,144,187,199],[321,349,335,343,377,176,265,356,344,332],[1151,1255,1195,1173,1184,1186,1188,1187,1203,593,1038,891],[90,88,100,83,62,113,80,89],[308,303,238,300,151,304,324,293,346,302],[59,38,50,41,42,35,40],[352,366,174,355,344,265,343,310,338,331],[91,89,93,90,117,85,60,106],[146,186,166,175,202,92,184,183,189],[82,67,96,44,80,79,88,76],[54,50,58,66,31,61,64],[343,266,344,172,308,336,364,350,359,333],[88,49,87,82,90,98,86,115],[20,47,49,51,54,48,40],[159,79,177,158,157,152,155,167,118],[1219,1183,1182,1115,1035,1186,591,1197,1167,887,1184,1175],[611,518,693,343,704,667,686,682,677,687,725],[607,599,634,305,677,604,603,580,452,605,591],[682,686,635,675,692,730,687,342,517,658,695],[662,296,573,598,592,584,553,593,595,443,591],[180,185,186,199,187,210,93,177,149],[197,136,179,185,156,182,180,178,99],[271,298,218,279,285,282,280,238,140],[1187,1151,890,593,1194,1188,1184,1173,1038,1186,1255,1203],[169,161,177,192,130,165,84,167,168],[50,42,43,41,66,39,36],[590,669,604,579,448,599,560,299,601,597,598],[174,191,206,179,184,142,177,180,90],[298,299,297,306,164,285,374,269,329,295],[181,172,162,138,170,195,86,169,168],[1184,1197,591,1182,1186,889,1167,1219,1183,1033,1115,1175],[644,695,691,679,667,687,340,681,770,686,517],[606,524,592,576,628,593,591,584,296,444,595],[94,127,154,138,135,74,136,141],[179,168,172,178,177,89,198,186,137],[302,299,291,300,298,149,260,305,280,370],[678,517,670,686,682,768,687,648,342,692,702],[302,290,304,376,333,303,306,298,279,153],[95,102,109,54,96,75,85,97],[150,154,146,78,152,151,162,173,119],[150,143,157,152,184,112,154,151,132],[36,41,54,40,25,44,42],[37,48,34,59,39,41,40],[681,603,638,611,584,303,454,607,606,605,596]
];
```
## --seed-contents--
```js
function testingSpecialSubsetSums(sets) {
return true;
}
const testSets = [
[81,88,75,42,87,84,86,65],[157,150,164,119,79,159,161,139,158],[673,465,569,603,629,592,584,300,601,599,600],[90,85,83,84,65,87,76,46],[165,168,169,190,162,85,176,167,127],[224,275,278,249,277,279,289,295,139],[354,370,362,384,359,324,360,180,350,270],[599,595,557,298,448,596,577,667,597,588,602],[175,199,137,88,187,173,168,171,174],[93,187,196,144,185,178,186,202,182],[157,155,81,158,119,176,152,167,159],[184,165,159,166,163,167,174,124,83],[1211,1212,1287,605,1208,1189,1060,1216,1243,1200,908,1210],[339,299,153,305,282,304,313,306,302,228],[94,104,63,112,80,84,93,96],[41,88,82,85,61,74,83,81],[90,67,84,83,82,97,86,41],[299,303,151,301,291,302,307,377,333,280],[55,40,48,44,25,42,41],[1038,1188,1255,1184,594,890,1173,1151,1186,1203,1187,1195],[76,132,133,144,135,99,128,154],[77,46,108,81,85,84,93,83],[624,596,391,605,529,610,607,568,604,603,453],[83,167,166,189,163,174,160,165,133],[308,281,389,292,346,303,302,304,300,173],[593,1151,1187,1184,890,1040,1173,1186,1195,1255,1188,1203],[68,46,64,33,60,58,65],[65,43,88,87,86,99,93,90],[83,78,107,48,84,87,96,85],[1188,1173,1256,1038,1187,1151,890,1186,1184,1203,594,1195],[302,324,280,296,294,160,367,298,264,299],[521,760,682,687,646,664,342,698,692,686,672],[56,95,86,97,96,89,108,120],[344,356,262,343,340,382,337,175,361,330],[47,44,42,27,41,40,37],[139,155,161,158,118,166,154,156,78],[118,157,164,158,161,79,139,150,159],[299,292,371,150,300,301,281,303,306,262],[85,77,86,84,44,88,91,67],[88,85,84,44,65,91,76,86],[138,141,127,96,136,154,135,76],[292,308,302,346,300,324,304,305,238,166],[354,342,341,257,348,343,345,321,170,301],[84,178,168,167,131,170,193,166,162],[686,701,706,673,694,687,652,343,683,606,518],[295,293,301,367,296,279,297,263,323,159],[1038,1184,593,890,1188,1173,1187,1186,1195,1150,1203,1255],[343,364,388,402,191,383,382,385,288,374],[1187,1036,1183,591,1184,1175,888,1197,1182,1219,1115,1167],[151,291,307,303,345,238,299,323,301,302],[140,151,143,138,99,69,131,137],[29,44,42,59,41,36,40],[348,329,343,344,338,315,169,359,375,271],[48,39,34,37,50,40,41],[593,445,595,558,662,602,591,297,610,580,594],[686,651,681,342,541,687,691,707,604,675,699],[180,99,189,166,194,188,144,187,199],[321,349,335,343,377,176,265,356,344,332],[1151,1255,1195,1173,1184,1186,1188,1187,1203,593,1038,891],[90,88,100,83,62,113,80,89],[308,303,238,300,151,304,324,293,346,302],[59,38,50,41,42,35,40],[352,366,174,355,344,265,343,310,338,331],[91,89,93,90,117,85,60,106],[146,186,166,175,202,92,184,183,189],[82,67,96,44,80,79,88,76],[54,50,58,66,31,61,64],[343,266,344,172,308,336,364,350,359,333],[88,49,87,82,90,98,86,115],[20,47,49,51,54,48,40],[159,79,177,158,157,152,155,167,118],[1219,1183,1182,1115,1035,1186,591,1197,1167,887,1184,1175],[611,518,693,343,704,667,686,682,677,687,725],[607,599,634,305,677,604,603,580,452,605,591],[682,686,635,675,692,730,687,342,517,658,695],[662,296,573,598,592,584,553,593,595,443,591],[180,185,186,199,187,210,93,177,149],[197,136,179,185,156,182,180,178,99],[271,298,218,279,285,282,280,238,140],[1187,1151,890,593,1194,1188,1184,1173,1038,1186,1255,1203],[169,161,177,192,130,165,84,167,168],[50,42,43,41,66,39,36],[590,669,604,579,448,599,560,299,601,597,598],[174,191,206,179,184,142,177,180,90],[298,299,297,306,164,285,374,269,329,295],[181,172,162,138,170,195,86,169,168],[1184,1197,591,1182,1186,889,1167,1219,1183,1033,1115,1175],[644,695,691,679,667,687,340,681,770,686,517],[606,524,592,576,628,593,591,584,296,444,595],[94,127,154,138,135,74,136,141],[179,168,172,178,177,89,198,186,137],[302,299,291,300,298,149,260,305,280,370],[678,517,670,686,682,768,687,648,342,692,702],[302,290,304,376,333,303,306,298,279,153],[95,102,109,54,96,75,85,97],[150,154,146,78,152,151,162,173,119],[150,143,157,152,184,112,154,151,132],[36,41,54,40,25,44,42],[37,48,34,59,39,41,40],[681,603,638,611,584,303,454,607,606,605,596]
];
testingSpecialSubsetSums(testSets);
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,49 @@
---
id: 5900f3d71000cf542c50fee9
title: '問題 106: 特殊和部分集合: メタ検証'
challengeType: 5
forumTopicId: 301730
dashedName: problem-106-special-subset-sums-meta-testing
---
# --description--
大きさが n である集合 A の要素の和を、$S(A)$ で表します。 空でなく互いに素な 2 つの部分集合 B と C について、次の性質が真の場合、それを「特殊和集合」と呼ぶことにします。
1. $S(B) ≠ S(C)$ である。すなわち、部分集合の和が等しくてはならない。
2. B が C より多くの要素を含むとき、$S(B) > S(C)$ である。
この問題では、与えられた集合が n 個の狭義単調増加要素を含み、上の 2 つ目のルールに沿っていると仮定します。
意外ですが、n = 4 の集合から得られる 25 個の可能な部分集合の対のうち、等価性の検証が必要なものは 1 つだけです (1 つ目のルール)。 同様に、n = 7 のとき、966 個の部分集合の対のうち検証が必要なものは 70 個だけです。
N = 12 のとき、得られる 261625 個の部分集合の対のうち、等価性の検証が必要なものはいくつありますか。
**注:** この問題は、問題 103 および問題 105 と関連しています。
# --hints--
`subsetSumsMetaTesting()``21384` を返す必要があります。
```js
assert.strictEqual(subsetSumsMetaTesting(), 21384);
```
# --seed--
## --seed-contents--
```js
function subsetSumsMetaTesting() {
return true;
}
subsetSumsMetaTesting();
```
# --solutions--
```js
// solution required
```

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
---
id: 5900f3d91000cf542c50feeb
title: '問題 108: ディオファントス逆数 (1)'
challengeType: 5
forumTopicId: 301732
dashedName: problem-108-diophantine-reciprocals-i
---
# --description--
次の式の x, y, n は正の整数です。
$$\frac{1}{x} + \frac{1}{y} = \frac{1}{n}$$
`n` = 4 のとき、ちょうど 3 つの相異なる解があります。
$$\begin{align} & \frac{1}{5} + \frac{1}{20} = \frac{1}{4}\\\\ \\\\ & \frac{1}{6} + \frac{1}{12} = \frac{1}{4}\\\\ \\\\ & \frac{1}{8} + \frac{1}{8} = \frac{1}{4} \end{align}$$
相異なる解の数が 1000 を超える最小の `n` の値を求めなさい。
# --hints--
`diophantineOne()``180180` を返す必要があります。
```js
assert.strictEqual(diophantineOne(), 180180);
```
# --seed--
## --seed-contents--
```js
function diophantineOne() {
return true;
}
diophantineOne();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,52 @@
---
id: 5900f3db1000cf542c50feec
title: '問題 109: ダーツ'
challengeType: 5
forumTopicId: 301733
dashedName: problem-109-darts
---
# --description--
ダーツゲームのターゲットボードは 20 等分され、それぞれのエリアに 1 から 20 までの番号が割り振られています。プレイヤーはそれに向けてダーツを 3 本投げます。
<img class="img-responsive center-block" alt="ダーツボード" src="https://cdn.freecodecamp.org/curriculum/project-euler/darts.png" style="background-color: white; padding: 10px;" />
ダーツのスコアは、ダーツが刺さったエリアの番号によって決まります。 外側にある赤と緑の輪よりも外に刺さったダーツは 0 点です。 この輪の内側にある黒と白の領域は、シングルスコアを表しています。 ただし、赤と緑の輪のうち、外側の輪はダブルスコア、中間の輪はトリプルスコアを表しています。
ボードの中央には、「ブル」または「ブルズアイ」と呼ばれる同心円が 2 つあります。 外側のブルは 25 点、内側のブルはその倍の 50 点です。
ルールには数多くのバリエーションがありますが、最も一般的なゲームでは 301 点 または 501 点から始め、現在の得点を最も早く 0 点にまで減らしたプレイヤーが勝ちます。 ただし、通常は「ダブルアウト」方式でプレイをします。この方式では、最後のダーツをダブル (ボード中央にあるダブルブルズアイを含む) に刺さなければ勝利できません。それ以外のダーツで現在の得点を 1 点以下に減らしてしまうと、その 3 本組のダーツのスコアは「バスト (無効)」になります。
プレイヤーが現在の得点で終了できることは「チェックアウト」と呼ばれます。チェックアウトでの最高スコアは 170: T20 T20 D25 (トリプルの 20 x 2 とダブルのブル) です。 スコア 6 でチェックアウトする方法は次ように 11 通りあります。
$$\begin{array} \text{D3} & & \\\\ D1 & D2 & \\\\ S2 & D2 & \\\\ D2 & D1 & \\\\ S4 & D1 & \\\\ S1 & S1 & D2 \\\\ S1 & T1 & D1 \\\\ S1 & S3 & D1 \\\\ D1 & D1 & D1 \\\\ D1 & S2 & D1 \\\\ S2 & S2 & D1 \end{array}$$
注意点として、D1 D2 と D2 D1 は異なるダブルで終了したので互いに異なるとみなされます。 ただし、S1 T1 D1 の組み合わせは T1 S1 D1 と同じとみなされます。 また、組み合わせを考える際にミスは含まれません。例えば D3 は、0 D3 および 0 0 D3 と同じです。 チェックアウトの方法は全部でなんと 42336 通りもあります。 プレイヤーが 100 未満のスコアでチェックアウトする方法は何通りありますか。
# --hints--
`darts()``38182` を返す必要があります。
```js
assert.strictEqual(darts(), 38182);
```
# --seed--
## --seed-contents--
```js
function darts() {
return true;
}
darts();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,182 @@
---
id: 5900f3781000cf542c50fe8a
title: '問題 11: 格子内の最大の積'
challengeType: 5
forumTopicId: 301734
dashedName: problem-11-largest-product-in-a-grid
---
# --description--
下の 20 × 20 の格子では、対角線上に沿って 4 つの数字が赤で示されています。
<div style='text-align: center;'>
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08<br>
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00<br>
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65<br>
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91<br>
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80<br>
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50<br>
32 98 81 28 64 23 67 10 <span style='color: red'><b>26</b></span> 38 40 67 59 54 70 66 18 38 64 70<br>
67 26 20 68 02 62 12 20 95 <span style='color: red'><b>63</b></span> 94 39 63 08 40 91 66 49 94 21<br>
24 55 58 05 66 73 99 26 97 17 <span style='color: red'><b>78</b></span> 78 96 83 14 88 34 89 63 72<br>
21 36 23 09 75 00 76 44 20 45 35 <span style='color: red'><b>14</b></span> 00 61 33 97 34 31 33 95<br>
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92<br>
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57<br>
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58<br>
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40<br>
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66<br>
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69<br>
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36<br>
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16<br>
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54<br>
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48<br>
</div>
これらの数字の積は 26 × 63 × 78 × 14 = 1788696 です。
与えられた `arr` 格子の中で、同じ方向 (上下左右または斜め) に連続する 4 つの数字の積のうち最大のものを求めなさい。
# --hints--
`largestGridProduct(testGrid)` は数値を返す必要があります。
```js
assert(typeof largestGridProduct(testGrid) === 'number');
```
`largestGridProduct(testGrid)` は 14169081 を返す必要があります。
```js
assert.strictEqual(largestGridProduct(testGrid), 14169081);
```
`largestGridProduct(grid)` は 70600674 を返す必要があります。
```js
assert.strictEqual(largestGridProduct(grid), 70600674);
```
# --seed--
## --seed-contents--
```js
function largestGridProduct(arr) {
return true;
}
// Only change code above this line
const grid = [
[8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8],
[49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0],
[81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36, 65],
[52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36, 91],
[22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
[24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50],
[32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70],
[67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21],
[24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72],
[21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95],
[78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92],
[16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57],
[86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],
[19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40],
[4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],
[88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69],
[4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36],
[20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36, 16],
[20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54],
[1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48]
];
const testGrid = [
[40, 17, 81, 18, 57],
[74, 4, 36, 16, 29],
[36, 42, 69, 73, 45],
[51, 54, 69, 16, 92],
[7, 97, 57, 32, 16]
];
largestGridProduct(testGrid);
```
# --solutions--
```js
function largestGridProduct(arr) {
let maxProduct = 0;
let currProduct = 0;
function maxProductChecker(n) {
if (n > maxProduct) {
return maxProduct = n;
}
}
// loop rows
for (let r = 0; r < arr.length; r++) {
// loop columns
for (let c = 0; c < arr[r].length; c++) {
const limit = arr[r].length - 3;
// check horizontal
if (c < limit) {
currProduct = arr[r][c] * arr[r][c + 1] * arr[r][c + 2] * arr[r][c + 3];
maxProductChecker(currProduct);
}
// check vertical
if (r < limit) {
currProduct = arr[r][c] * arr[r + 1][c] * arr[r + 2][c] * arr[r + 3][c];
maxProductChecker(currProduct);
}
// check diagonal [\]
if (c < limit && r < limit) {
currProduct = arr[r][c] * arr[r + 1][c + 1] * arr[r + 2][c + 2] * arr[r + 3][c + 3];
maxProductChecker(currProduct);
}
// check diagonal [/]
if (c > 3 && r < limit) {
currProduct = arr[r][c] * arr[r + 1][c - 1] * arr[r + 2][c - 2] * arr[r + 3][c - 3];
maxProductChecker(currProduct);
}
}
}
return maxProduct;
}
const grid = [ [8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8],
[49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0],
[81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36, 65],
[52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36, 91],
[22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
[24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50],
[32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70],
[67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21],
[24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72],
[21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95],
[78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92],
[16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57],
[86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],
[19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40],
[4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],
[88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69],
[4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36],
[20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36, 16],
[20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54],
[1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48]
];
const testGrid = [
[40, 17, 81, 18, 57],
[74, 4, 36, 16, 29],
[36, 42, 69, 73, 45],
[51, 54, 69, 16, 92],
[7, 97, 57, 32, 16]
];
```

View File

@ -0,0 +1,46 @@
---
id: 5900f3db1000cf542c50feed
title: '問題 110: ディオファントス逆数 (2)'
challengeType: 5
forumTopicId: 301735
dashedName: problem-110-diophantine-reciprocals-ii
---
# --description--
次の式の x, y, n は正の整数です。
$$\frac{1}{x} + \frac{1}{y} = \frac{1}{n}$$
`n` = 1260 の場合に 113 個の相異なる解があり、1260 は相異なる解の総数が 100 を超える `n` の最小値です。
相異なる解の数が 400 万を超える最小の `n` を求めなさい。
**注:** これは、問題 108 をかなり難しくした問題です。総当たりで解ける限界をはるかに超えているので、賢い方法が必要です。
# --hints--
`diophantineTwo()``9350130049860600` を返す必要があります。
```js
assert.strictEqual(diophantineTwo(), 9350130049860600);
```
# --seed--
## --seed-contents--
```js
function diophantineTwo() {
return true;
}
diophantineTwo();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,61 @@
---
id: 5900f3db1000cf542c50feee
title: '問題 111: 素数内の反復数字'
challengeType: 5
forumTopicId: 301736
dashedName: problem-111-primes-with-runs
---
# --description--
同じ数字が繰り返し使われている 4 桁の素数について考える場合、当然ながら、すべての桁が同じ数字にはなり得ません。1111 は 11 で割り切れ、22222 は 22で割り切れ、以降も同様だからです。 しかし、1 を 3 つ含む 4 桁の素数は 9 つあります。
$$1117, 1151, 1171, 1181, 1511, 1811, 2111, 4111, 8111$$
反復数字を d とし、n 桁の素数について反復数字の最大個数を $M(n, d)$ と表すことにします。また、そのような素数の個数を $N(n, d)$ と表し、これらの素数の和を $S(n, d)$ と表すことにします。
$M(4, 1) = 3 は、4 桁の素数に含まれる反復数字 1 が最大 3 個であること、$N(4, 1) = 9 は、そのような 4 桁の素数が 9 つあること、そして $S(4, 1) = 22275$ は、それらの素数の和を表します。 d = 0 のとき、$M(4, 0) = 2$ (反復数字は最大 2 つ) で、$N(4, 0) = 13$ (そのようなケースが 13 個) であることが分かります。
同様にして、4 桁の素数に対して次の結果が得られます。
| 数字 d | $M(4, d)$ | $N(4, d)$ | $S(4, d)$ |
| ---- | --------- | --------- | --------- |
| 0 | 2 | 13 | 67061 |
| 1 | 3 | 9 | 22275 |
| 2 | 3 | 1 | 2221 |
| 3 | 3 | 12 | 46214 |
| 4 | 3 | 2 | 8888 |
| 5 | 3 | 1 | 5557 |
| 6 | 3 | 1 | 6661 |
| 7 | 3 | 9 | 57863 |
| 8 | 3 | 1 | 8887 |
| 9 | 3 | 7 | 48073 |
d = 0 9 のとき、$S(4, d)$ の総和は 273700 です。 $S(10, d)$ の総和を求めなさい。
# --hints--
`primesWithRuns()``612407567715` を返す必要があります。
```js
assert.strictEqual(primesWithRuns(), 612407567715);
```
# --seed--
## --seed-contents--
```js
function primesWithRuns() {
return true;
}
primesWithRuns();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,48 @@
---
id: 5900f3dd1000cf542c50feef
title: '問題 112: 弾み数'
challengeType: 5
forumTopicId: 301738
dashedName: problem-112-bouncy-numbers
---
# --description--
ある数を左から右へ見ていき、すべての数字がその左側の数字を下回らない場合、その数は増加数と呼ばれます。例えば 134468 です。
同様に、すべての数字がその右側の数字を下回らない場合、その数は減少数と呼ばれます。例えば 66420 です。
増加数、減少数のどちらでもない正の整数を「弾み」数と呼ぶことにします。例えば 155349 です。
当然、100 未満には弾み数がありませんが、1000 未満の数の半数強 (525 個) が弾み数です。 実際、弾み数の割合が最初に 50% に達する最小の数は 538 です。
意外にも弾み数の割合は次第に増え、21780 に達する時点で弾み数の割合は 90% に達します。
弾み数の割合がちょうど 99% になる最小の数を求めなさい。
# --hints--
`bouncyNumbers()``1587000` を返す必要があります。
```js
assert.strictEqual(bouncyNumbers(), 1587000);
```
# --seed--
## --seed-contents--
```js
function bouncyNumbers() {
return true;
}
bouncyNumbers();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,46 @@
---
id: 5900f3dd1000cf542c50fef0
title: '問題 113: 弾み数ではない数'
challengeType: 5
forumTopicId: 301739
dashedName: problem-113-non-bouncy-numbers
---
# --description--
ある数を左から右へ見ていき、すべての数字がその左側の数字を下回らない場合、その数は増加数と呼ばれます。例えば 134468 です。
同様に、すべての数字がその右側の数字を下回らない場合、その数は減少数と呼ばれます。例えば 66420 です。
増加数、減少数のどちらでもない正の整数を「弾み」数と呼ぶことにします。例えば 155349 です。
n が大きくなるにつれ、n 未満の弾み数の割合も大きくなります。弾み数ではない数は 100万未満で 12951 個、${10}^{10}$ 未満で 277032 個しかありません。
グーゴル数 (${10}^{100}$) 未満で弾み数でない数はいくつありますか。
# --hints--
`nonBouncyNumbers()``51161058134250` を返す必要があります。
```js
assert.strictEqual(nonBouncyNumbers(), 51161058134250);
```
# --seed--
## --seed-contents--
```js
function nonBouncyNumbers() {
return true;
}
nonBouncyNumbers();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3e01000cf542c50fef2
title: '問題 114: ブロックの組み合わせを数え上げる (1)'
challengeType: 5
forumTopicId: 301740
dashedName: problem-114-counting-block-combinations-i
---
# --description--
長さ 7 単位の 1 列に、長さ 3 単位以上の赤ブロックが置かれています。2 つの赤ブロック (長さが異なっていても良い) がある場合、それらは少なくとも 1 つの黒マスで区切られています。 このようにブロックを置く方法はちょうど 17 通りあります。
<img class="img-responsive center-block" alt="長さ 7 単位の列に長さ 3 単位以上のブロックを置く方法" src="https://cdn.freecodecamp.org/curriculum/project-euler/counting-block-combinations-i.png" style="background-color: white; padding: 10px;" />
長さ 50 単位の 1 列にブロックを置く方法は何通りありますか。
**注:** 上の例ではあり得ませんが、通常はブロックの大きさが混在することが許されます。 例えば、長さ 8 単位の 1 列に赤 (3)、黒 (1)、赤 (4) を使用できます。
# --hints--
`countingBlockOne()``16475640049` を返す必要があります。
```js
assert.strictEqual(countingBlockOne(), 16475640049);
```
# --seed--
## --seed-contents--
```js
function countingBlockOne() {
return true;
}
countingBlockOne();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,50 @@
---
id: 5900f3df1000cf542c50fef1
title: '問題 115: ブロックの組み合わせを数え上げる (2)'
challengeType: 5
forumTopicId: 301741
dashedName: problem-115-counting-block-combinations-ii
---
# --description--
長さ `n` 単位の 1 列に、長さ `m` 単位以上の赤ブロックが置かれています。2 つの赤ブロック (長さが異なっていても良い) がある場合、それらは少なくとも 1 つの黒マスで区切られています。
列を埋める方法が何通りあるかを、fill-count 関数 $F(m, n)$ で表すことにします。
例えば、$F(3, 29) = 673135$, $F(3, 30) = 1089155$ です。
したがって、m = 3 のとき、fill-count 関数が初めて 100 万を超える n の最小値は 30 です。
同様に、m = 10 のときに $F(10, 56) = 880711$ および $F(10, 57) = 1148904$ であることが分かります。したがって、fill-count 関数が初めて100 万を超える n の最小値は 57 です。
m = 50のとき、fill-count 関数が初めて 100 万を超える `n` の最小値を見つけなさい。
**注:** これは、問題 114 をより難しくした問題です。
# --hints--
`countingBlockTwo()``168` を返す必要があります。
```js
assert.strictEqual(countingBlockTwo(), 168);
```
# --seed--
## --seed-contents--
```js
function countingBlockTwo() {
return true;
}
countingBlockTwo();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,54 @@
---
id: 5900f3e01000cf542c50fef3
title: '問題 116: 赤タイル・緑タイル・青タイルのいずれか'
challengeType: 5
forumTopicId: 301742
dashedName: problem-116-red-green-or-blue-tiles
---
# --description--
黒の正方形タイルを 5 枚並べた列を、赤 (長さ 2)、緑 (長さ 3)、または青 (長さ 4) のいずれか 1 色の長方形タイルで置き換えます。
赤のタイルを選んだ場合、それを行う方法はちょうど 7 通りあります。
<img class="img-responsive center-block" alt="長さ 5 単位の列に赤のタイルを置く場合に考えられる方法" src="https://cdn.freecodecamp.org/curriculum/project-euler/red-green-or-blue-tiles-1.png" style="background-color: white; padding: 10px;" />
緑のタイルを選んだ場合は 3 通りあります。
<img class="img-responsive center-block" alt="長さ 5 単位の列に緑のタイルを置く場合に考えられる方法" src="https://cdn.freecodecamp.org/curriculum/project-euler/red-green-or-blue-tiles-2.png" style="background-color: white; padding: 10px;" />
青のタイルを選んだ場合は 2 通りあります。
<img class="img-responsive center-block" alt="長さ 5 単位の列に青のタイルを置く場合に考えられる方法" src="https://cdn.freecodecamp.org/curriculum/project-euler/red-green-or-blue-tiles-3.png" style="background-color: white; padding: 10px;" />
1 列に 1 色だけ使えるものとすると、長さ 5 単位の列にある黒のタイルを置き換える方法は 7 + 3 + 2 = 12 通りあります。 1 列に 1 色だけ使用でき、かつ、少なくとも 1 枚の色付きタイルを使用する必要がある場合、長さ 50 単位の黒のタイルの列を置き換える方法は何通りありますか。
**注:** この問題は、問題 117と関連しています。
# --hints--
`redGreenBlueOne()``20492570929` を返す必要があります 。
```js
assert.strictEqual(redGreenBlueOne(), 20492570929);
```
# --seed--
## --seed-contents--
```js
function redGreenBlueOne() {
return true;
}
redGreenBlueOne();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3e21000cf542c50fef4
title: '問題 117: 赤タイル・緑タイル・青タイルの組み合わせ'
challengeType: 5
forumTopicId: 301743
dashedName: problem-117-red-green-and-blue-tiles
---
# --description--
正方形の黒のタイルと、赤 (長さ 2)、緑 (長さ 3)、または青 (長さ 4) の長方形タイルを組み合わせて、長さ 5 単位の 1 列にタイルを敷く方法はちょうど 15 通りあります。
<img class="img-responsive center-block" alt="長さ 5 単位の列に赤、緑、青のタイルを置く場合に考えられる方法" src="https://cdn.freecodecamp.org/curriculum/project-euler/red-green-and-blue-tiles.png" style="background-color: white; padding: 10px;" />
長さ 50 単位の 1 列にタイルを敷く方法は何通りありますか。
**注**: この問題は、問題 116と関連しています。
# --hints--
`redGreenBlueTilesTwo()``100808458960497` を返す必要があります 。
```js
assert.strictEqual(redGreenBlueTilesTwo(), 100808458960497);
```
# --seed--
## --seed-contents--
```js
function redGreenBlueTilesTwo() {
return true;
}
redGreenBlueTilesTwo();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,40 @@
---
id: 5900f3e21000cf542c50fef5
title: '問題 118: パンデジタル素数集合'
challengeType: 5
forumTopicId: 301744
dashedName: problem-118-pandigital-prime-sets
---
# --description--
1 から 9 までのすべての数字を自由につなげて 10 進数の整数を作ると、さまざまな集合を作ることができます。 興味深いことに、集合 $\\{2, 5, 47, 89, 631\\}$ は、それに属するすべての要素が素数です。
1 から 9 までの数字をそれぞれちょうど 1 回含む相異なる集合のうち、素数のみを含むものはいくつありますか。
# --hints--
`pandigitalPrimeSets()``44680` を返す必要があります。
```js
assert.strictEqual(pandigitalPrimeSets(), 44680);
```
# --seed--
## --seed-contents--
```js
function pandigitalPrimeSets() {
return true;
}
pandigitalPrimeSets();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3e41000cf542c50fef6
title: '問題 119: 各位の和の累乗'
challengeType: 5
forumTopicId: 301745
dashedName: problem-119-digit-power-sum
---
# --description--
512 は興味深い数字です。各位の和の累乗と等しいからです。すなわち、$5 + 1 + 2 = 8$, $8^3 = 512$ です。 この性質を持つ数は他にも $614656 = 28^4$ などがあります。
$a_n$ をこの数列の第 $n$ 項と定義し、また、和を持つには 2 桁以上の数でなければならないものとします。
$a_2 = 512$ と $a_{10} = 614656$ が与えられます。
$a_{30} $ を求めなさい。
# --hints--
`digitPowerSum()``248155780267521` を返す必要があります。
```js
assert.strictEqual(digitPowerSum(), 248155780267521);
```
# --seed--
## --seed-contents--
```js
function digitPowerSum() {
return true;
}
digitPowerSum();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,139 @@
---
id: 5900f3781000cf542c50fe8b
title: '問題 12: 約数が多い三角数'
challengeType: 5
forumTopicId: 301746
dashedName: problem-12-highly-divisible-triangular-number
---
# --description--
三角数の数列は、自然数の和を求めることによって得られます。 したがって 7 番目の三角数は 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28 になります。 最初の 10 項は次のとおりです。
<div style='text-align: center;'>1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...</div>
最初の 7 つの三角数の約数を列挙すると、次のようになります。
<div style='padding-left: 4em;'><b>1:</b> 1</div>
<div style='padding-left: 4em;'><b>3:</b> 1, 3</div>
<div style='padding-left: 4em;'><b>6:</b> 1, 2, 3, 6</div>
<div style='padding-left: 4em;'><b>10:</b> 1, 2, 5, 10</div>
<div style='padding-left: 4em;'><b>15:</b> 1, 3, 5, 15</div>
<div style='padding-left: 4em;'><b>21:</b> 1, 3, 7, 21</div>
<div style='padding-left: 4em;'><b>28:</b> 1, 2, 4, 7, 14, 28</div>
5 つより多い約数を持つ最初の三角数は 28 であることが分かります。
`n` 個より多い約数を持つ最初の三角数の値を求めなさい。
# --hints--
`divisibleTriangleNumber(5)` は数値を返す必要があります。
```js
assert(typeof divisibleTriangleNumber(5) === 'number');
```
`divisibleTriangleNumber(5)` は 28 を返す必要があります。
```js
assert.strictEqual(divisibleTriangleNumber(5), 28);
```
`divisibleTriangleNumber(23)` は 630 を返す必要があります。
```js
assert.strictEqual(divisibleTriangleNumber(23), 630);
```
`divisibleTriangleNumber(167)` は 1385280 を返す必要があります。
```js
assert.strictEqual(divisibleTriangleNumber(167), 1385280);
```
`divisibleTriangleNumber(374)` は 17907120 を返す必要があります。
```js
assert.strictEqual(divisibleTriangleNumber(374), 17907120);
```
`divisibleTriangleNumber(500)` は 76576500 を返す必要があります。
```js
assert.strictEqual(divisibleTriangleNumber(500), 76576500);
```
# --seed--
## --seed-contents--
```js
function divisibleTriangleNumber(n) {
return true;
}
divisibleTriangleNumber(500);
```
# --solutions--
```js
function divisibleTriangleNumber(n) {
if (n === 1) return 3;
let counter = 1;
let triangleNumber = counter++;
while (noOfFactors(triangleNumber) < n) {
triangleNumber += counter++;
}
return triangleNumber;
}
function noOfFactors(num) {
const primeFactors = getPrimeFactors(num);
let prod = 1;
for(let p in primeFactors) {
prod *= (primeFactors[p] + 1)
}
return prod;
}
function getPrimeFactors(num) {
let n = num;
let primes = {};
let p = 2;
let sqrt = Math.sqrt(num);
function checkAndUpdate(inc) {
if (n % p === 0) {
const curr = primes[p];
if (curr) {
primes[p]++
} else {
primes[p] = 1;
}
n /= p;
} else {
p += inc;
}
}
while(p === 2 && p <= n) {
checkAndUpdate(1);
}
while (p <= n && p <= sqrt) {
checkAndUpdate(2);
}
if(Object.keys(primes).length === 0) {
primes[num] = 1;
} else if(n !== 1) {
primes[n] = 1;
}
return primes;
}
```

View File

@ -0,0 +1,42 @@
---
id: 5900f3e41000cf542c50fef7
title: '問題 120: 平方数で除した余り'
challengeType: 5
forumTopicId: 301747
dashedName: problem-120-square-remainders
---
# --description--
${(a 1)}^n + {(a + 1)}^n$ を $a^2$ で除した余りを `r` とします。
例えば、$a = 7$ かつ $n = 3$ のとき、$r = 42: 6^3 + 8^3 = 728 ≡ 42 \\ \text{mod}\\ 49$ です。 `n` が変わると `r` も変わりますが、$a = 7$ のときに $r_{max} = 42$ となります。
$3 ≤ a ≤ 1000$ のとき、$\sum{r}_{max}$ を求めなさい。
# --hints--
`squareRemainders()``333082500` を返す必要があります。
```js
assert.strictEqual(squareRemainders(), 333082500);
```
# --seed--
## --seed-contents--
```js
function squareRemainders() {
return true;
}
squareRemainders();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3e51000cf542c50fef8
title: '問題 121: 円盤ゲームの賞金額'
challengeType: 5
forumTopicId: 301748
dashedName: problem-121-disc-game-prize-fund
---
# --description--
袋の中に、赤い円盤 1 枚と青い円盤 1 枚が入っています。 運で勝負が決まるゲームにおいて、プレイヤーは無作為に円盤を取り、その色が記録されます。 ターンごとに円盤が袋に戻され、赤い円盤が 1 枚追加され、またプレイヤーが無作為に円盤を 1 枚取ります。
プレイヤーは 1 ポンド払ってゲームに参加し、ゲーム終了時に赤い円盤よりも青い円盤を多く取っていたら勝ちです。
このゲームが 4 ターン行われた場合、プレイヤーの勝率はちょうど 11/120 なので、胴元が確率的に損失を出さないようにこのゲームの勝利に割り当てるべき賞金額は、最大 10 ポンドです。 なお、支払いは 1 ポンド単位であり、ゲームをプレイするために支払った最初の 1 ポンドも含まれています。したがってこの例では、プレイヤーが実際に得る利益は 9 ポンドになります。
15 ターンが行われる 1 回のゲームに割り当てるべき最大賞金額を求めなさい。
# --hints--
`discGamePrize()``2269` を返す必要があります。
```js
assert.strictEqual(discGamePrize(), 2269);
```
# --seed--
## --seed-contents--
```js
function discGamePrize() {
return true;
}
discGamePrize();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,52 @@
---
id: 5900f3e61000cf542c50fef9
title: '問題 122: 効率的な累乗法'
challengeType: 5
forumTopicId: 301749
dashedName: problem-122-efficient-exponentiation
---
# --description--
$n^{15}$ の最も単純な計算方法では、14 回の乗算が必要です。
$$n × n × \ldots × n = n^{15}$$
しかし、2 進法を使えば 6 回の乗算で計算できます。
$$\begin{align} & n × n = n^2\\\\ & n^2 × n^2 = n^4\\\\ & n^4 × n^4 = n^8\\\\ & n^8 × n^4 = n^{12}\\\\ & n^{12} × n^2 = n^{14}\\\\ & n^{14} × n = n^{15} \end{align}$$
しかし、わずか 5 回の乗算で計算することも可能です。
$$\begin{align} & n × n = n^2\\\\ & n^2 × n = n^3\\\\ & n^3 × n^3 = n^6\\\\ & n^6 × n^6 = n^{12}\\\\ & n^{12} × n^3 = n^{15} \end{align}$$
ここで、$n^k$ を計算するための最小の乗算回数を $m(k)$ とします。例えば $m(15) = 5$ です。
$1 ≤ a ≤ 200$ のとき、$\sum{m(k)}$ を求めなさい。
# --hints--
`efficientExponentation()``1582` を返す必要があります。
```js
assert.strictEqual(efficientExponentation(), 1582);
```
# --seed--
## --seed-contents--
```js
function efficientExponentation() {
return true;
}
efficientExponentation();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3e71000cf542c50fefa
title: '問題 123: 素数の平方数で除した余り'
challengeType: 5
forumTopicId: 301750
dashedName: problem-123-prime-square-remainders
---
# --description--
$n$ 番目の素数 (2, 3, 5, 7, 11, ...) を $p_n$ とし、${(p_n1)}^n + {(p_n+1)}^n$ を ${p_n}^2$ で除した余りを $r$ とします。
例えば、$n = 3 のとき、p_3 = 5$, $4^3 + 6^3 = 280 ≡ 5\\ mod\\ 25$ となります。
余りが初めて $10^9$ を超える $n$ の最小値は 7037です。
余りが初めて $10^{10}$ を超える $n$ の最小値を求めなさい。
# --hints--
`primeSquareRemainders()``21035` を返す必要があります。
```js
assert.strictEqual(primeSquareRemainders(), 21035);
```
# --seed--
## --seed-contents--
```js
function primeSquareRemainders() {
return true;
}
primeSquareRemainders();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,142 @@
---
id: 5900f3e81000cf542c50fefb
title: '問題 124: 順序付き累乗根'
challengeType: 5
forumTopicId: 301751
dashedName: problem-124-ordered-radicals
---
# --description--
$n$ の累乗根 $rad(n)$ は、$n$ の相異なる素因数の積です。 例えば、$504 = 2^3 × 3^2 × 7$ なので、$rad(504) = 2 × 3 × 7 = 42$ です。
$1 ≤ n ≤ 10$ に対して $rad(n)$ を求め、それらを $rad(n)$ でソートし、累乗根の値が等しい場合は $n$ でソートすると、次のようになります。
<div style="text-align: center;">
<table cellpadding="2" cellspacing="0" border="0" align="center">
<tbody>
<tr>
<td colspan="2">$未ソート$</td>
<td></td>
<td colspan="3">$ソート済み$</td>
</tr>
<tr>
<td>$n$</td>
<td>$rad(n)$</td>
<td></td>
<td>$n$</td>
<td>$rad(n)$</td>
<td>$k$</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td></td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td></td>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td></td>
<td>4</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>2</td>
<td></td>
<td>8</td>
<td>2</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>5</td>
<td></td>
<td>3</td>
<td>3</td>
<td>5</td>
</tr>
<tr>
<td>6</td>
<td>6</td>
<td></td>
<td>9</td>
<td>3</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>7</td>
<td></td>
<td>5</td>
<td>5</td>
<td>7</td>
</tr>
<tr>
<td>8</td>
<td>2</td>
<td></td>
<td>6</td>
<td>6</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td>3</td>
<td></td>
<td>7</td>
<td>7</td>
<td>9</td>
</tr>
<tr>
<td>10</td>
<td>10</td>
<td></td>
<td>10</td>
<td>10</td>
<td>10</td>
</tr>
</tbody>
</table>
</div><br>
ソート済みの $n$ 列の $k$ 番目の要素を $E(k)$ とします。例えば、$E(4) = 8$, $E(6) = 9$ です。 $1 ≤ n ≤ 100000$ のとき、$rad(n)$ をソートした場合の $E(10000)$ を求めなさい。
# --hints--
`orderedRadicals()``21417` を返す必要があります。
```js
assert.strictEqual(orderedRadicals(), 21417);
```
# --seed--
## --seed-contents--
```js
function orderedRadicals() {
return true;
}
orderedRadicals();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,42 @@
---
id: 5900f3e91000cf542c50fefc
title: '問題 125: 回文数の和'
challengeType: 5
forumTopicId: 301752
dashedName: problem-125-palindromic-sums
---
# --description--
回文数 595 は、連続する平方数の和 ($6^2 + 7^2 + 8^2 + 9^2 + 10^2 + 10^2 + 11^2 + 12^2$) として表せる興味深い数です。
連続した平方数の和で表せる 1,000 未満の回文数はちょうど 11 個あり、それらの回文数の和は 4164 です。 なお、この問題では正の整数の平方数のみを扱うので、$1 = 0^2 + 1^2$ は含まれません。
回文数であり、かつ、連続する平方数の和として表すことができる、$10^8$ 未満の数の総和を求めなさい。
# --hints--
`palindromicSums()``2906969179` を返す必要があります。
```js
assert.strictEqual(palindromicSums(), 2906969179);
```
# --seed--
## --seed-contents--
```js
function palindromicSums() {
return true;
}
palindromicSums();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,50 @@
---
id: 5900f3ea1000cf542c50fefd
title: '問題 126: 直方体の層'
challengeType: 5
forumTopicId: 301753
dashedName: problem-126-cuboid-layers
---
# --description--
寸法が 3 x 2 x 1 の直方体の表面をすべて覆うには、少なくとも 22 個の立方体が必要です。
<img class="img-responsive center-block" alt="1 x 1 x 1 の立方体 22 個 で覆われた 3 x 2 x 1 の直方体" src="https://cdn.freecodecamp.org/curriculum/project-euler/cuboid-layers.png" style="background-color: white; padding: 10px;" />
この立体に 2 層目を加える場合、表面をすべて覆うには 46 個の立方体が必要になります。さらに 3 層目では 78 個、4 層目では 118 個の立方体が必要です。
しかし、5 × 1 × 1 の直方体でも 1 層目に 22 個の立方体が必要であり、同様に、5 × 3 × 1, 7 × 2 × 1, 11 × 1 × 1 の直方体はいずれも 1 層目が 46 個の立方体からなります。
いずれか 1 つの層が $n$ 個の立方体からなるような直方体の個数を、$C(n)$ とします。 したがって、$C(22) = 2$, $C(46) = 4$, $C(78) = 5$, $C(118) = 8$ です。
$C(n) = 10$ のとき、最小の $n$ が 154 であることが分かります。
$C(n) = 1000$ のとき、$n$ の最小値を求めなさい。
# --hints--
`cuboidLayers()``18522` を返す必要があります。
```js
assert.strictEqual(cuboidLayers(), 18522);
```
# --seed--
## --seed-contents--
```js
function cuboidLayers() {
return true;
}
cuboidLayers();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,56 @@
---
id: 5900f3ec1000cf542c50fefe
title: '問題 127: abc-hit'
challengeType: 5
forumTopicId: 301754
dashedName: problem-127-abc-hits
---
# --description--
$n$ の累乗根 $rad(n)$ は、$n$ の相異なる素数の積です。 例えば、$504 = 2^3 × 3^2 × 7$ なので、$rad(504) = 2 × 3 × 7 = 42$ です。
以下が成り立つとき、正の整数 (a, b, c) の三つ組数を "abc-hit" と呼ぶことにします。
1. $GCD(a, b) = GCD(a, c) = GCD(b, c) = 1$
2. $a &lt; b$
3. $a + b = c$
4. $rad(abc) &lt; c$
例えば、(5, 27, 32) は abc-hit です。
1. $GCD(5, 27) = GCD(5, 32) = GCD(27, 32) = 1$
2. $5 &lt; 27$
3. $5 + 27 = 32$
4. $rad(4320) = 30 &lt; 32$
abc-hit は極めてまれです。$c &lt; 1000$ のとき、abc-hits はわずか 31 個であり $\sum{c} = 12523$ です。
$c &lt; 120000$ のとき、$\sum{c}$ を求めなさい。
# --hints--
`abcHits()``18407904` を返す必要があります。
```js
assert.strictEqual(abcHits(), 18407904);
```
# --seed--
## --seed-contents--
```js
function abcHits() {
return true;
}
abcHits();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,54 @@
---
id: 5900f3ec1000cf542c50feff
title: '問題 128: 六角形タイルの差'
challengeType: 5
forumTopicId: 301755
dashedName: problem-128-hexagonal-tile-differences
---
# --description--
1 番の六角形タイルは、12 時の位置から反時計回りに配置された 2 番から 7 番の 6 枚の六角形タイルの輪に囲まれています。
同様に、8 番から 19 番、20 番から 37 番、38 番から 61 番、… という具合に新しい輪が追加されていきます。 下図は、最初の 3 個の輪を示しています。
<img class="img-responsive center-block" alt="1 37 番の六角形タイルを並べて作られた最初の 3 つの輪。タイル 8 番と 17 番は色付き" src="https://cdn.freecodecamp.org/curriculum/project-euler/hexagonal-tile-differences.png" style="background-color: white; padding: 10px;" />
タイル $n$ 番と、それに隣接する 6 枚の各タイルとの差を求め、差が素数となるタイルの枚数を $PD(n) とします。
例えば、タイル 8 番の周りを時計回りに差を求めると、12, 29, 11, 6, 1, 13 となります。 したがって、$PD(8) = 3$ です。
同様に、タイル 17 番とその周囲との差は 1, 17, 16, 1, 11, 10 なので、$PD(17) = 2$ です。
$PD(n)$ の最大値が $3$ であることを示すことができます。
$PD(n) = 3$ が成り立つすべてのタイルを昇順に並べて数列を作ると、第 10 項はタイル 271 番です。
この数列の 第 2000 項のタイルの番号を求めなさい。
# --hints--
`hexagonalTile()``14516824220` を返す必要があります。
```js
assert.strictEqual(hexagonalTile(), 14516824220);
```
# --seed--
## --seed-contents--
```js
function hexagonalTile() {
return true;
}
hexagonalTile();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3ef1000cf542c50ff01
title: '問題 129: レピュニット数の被整除性'
challengeType: 5
forumTopicId: 301756
dashedName: problem-129-repunit-divisibility
---
# --description--
1 のみで構成される数はレピュニット数と呼ばれます。 ここでは、長さ $k$ のレピュニット数を $R(k)$ とします。例えば、$R(6) = 111111$ です。
$n$ を正の整数とし、$GCD(n, 10) = 1$ が与えられる場合、$R(k)$ が $n$ で割り切れるような値 $k$ が必ず存在することを証明できます。また、そのような $k$ の最小値を $A(n)$ とします。例えば、$A(7) = 6$, $A(41) = 5$ です。
$A(n)$ が初めて 10 を超えるときの $n$ の最小値は 17 です。
$A(n)$ が初めて 100 万を超えるときの $n$ の最小値を求めなさい。
# --hints--
`repunitDivisibility()``1000023` を返す必要があります。
```js
assert.strictEqual(repunitDivisibility(), 1000023);
```
# --seed--
## --seed-contents--
```js
function repunitDivisibility() {
return true;
}
repunitDivisibility();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,286 @@
---
id: 5900f37a1000cf542c50fe8c
title: '問題 13: 大きな数の和'
challengeType: 5
forumTopicId: 301757
dashedName: problem-13-large-sum
---
# --description--
下に、50 桁の数が 100 個あります。これらの和の最初の10 桁を求めなさい。
<div style='padding-left: 4em;'>
37107287533902102798797998220837590246510135740250<br>
46376937677490009712648124896970078050417018260538<br>
74324986199524741059474233309513058123726617309629<br>
91942213363574161572522430563301811072406154908250<br>
23067588207539346171171980310421047513778063246676<br>
89261670696623633820136378418383684178734361726757<br>
28112879812849979408065481931592621691275889832738<br>
44274228917432520321923589422876796487670272189318<br>
47451445736001306439091167216856844588711603153276<br>
70386486105843025439939619828917593665686757934951<br>
62176457141856560629502157223196586755079324193331<br>
64906352462741904929101432445813822663347944758178<br>
92575867718337217661963751590579239728245598838407<br>
58203565325359399008402633568948830189458628227828<br>
80181199384826282014278194139940567587151170094390<br>
35398664372827112653829987240784473053190104293586<br>
86515506006295864861532075273371959191420517255829<br>
71693888707715466499115593487603532921714970056938<br>
54370070576826684624621495650076471787294438377604<br>
53282654108756828443191190634694037855217779295145<br>
36123272525000296071075082563815656710885258350721<br>
45876576172410976447339110607218265236877223636045<br>
17423706905851860660448207621209813287860733969412<br>
81142660418086830619328460811191061556940512689692<br>
51934325451728388641918047049293215058642563049483<br>
62467221648435076201727918039944693004732956340691<br>
15732444386908125794514089057706229429197107928209<br>
55037687525678773091862540744969844508330393682126<br>
18336384825330154686196124348767681297534375946515<br>
80386287592878490201521685554828717201219257766954<br>
78182833757993103614740356856449095527097864797581<br>
16726320100436897842553539920931837441497806860984<br>
48403098129077791799088218795327364475675590848030<br>
87086987551392711854517078544161852424320693150332<br>
59959406895756536782107074926966537676326235447210<br>
69793950679652694742597709739166693763042633987085<br>
41052684708299085211399427365734116182760315001271<br>
65378607361501080857009149939512557028198746004375<br>
35829035317434717326932123578154982629742552737307<br>
94953759765105305946966067683156574377167401875275<br>
88902802571733229619176668713819931811048770190271<br>
25267680276078003013678680992525463401061632866526<br>
36270218540497705585629946580636237993140746255962<br>
24074486908231174977792365466257246923322810917141<br>
91430288197103288597806669760892938638285025333403<br>
34413065578016127815921815005561868836468420090470<br>
23053081172816430487623791969842487255036638784583<br>
11487696932154902810424020138335124462181441773470<br>
63783299490636259666498587618221225225512486764533<br>
67720186971698544312419572409913959008952310058822<br>
95548255300263520781532296796249481641953868218774<br>
76085327132285723110424803456124867697064507995236<br>
37774242535411291684276865538926205024910326572967<br>
23701913275725675285653248258265463092207058596522<br>
29798860272258331913126375147341994889534765745501<br>
18495701454879288984856827726077713721403798879715<br>
38298203783031473527721580348144513491373226651381<br>
34829543829199918180278916522431027392251122869539<br>
40957953066405232632538044100059654939159879593635<br>
29746152185502371307642255121183693803580388584903<br>
41698116222072977186158236678424689157993532961922<br>
62467957194401269043877107275048102390895523597457<br>
23189706772547915061505504953922979530901129967519<br>
86188088225875314529584099251203829009407770775672<br>
11306739708304724483816533873502340845647058077308<br>
82959174767140363198008187129011875491310547126581<br>
97623331044818386269515456334926366572897563400500<br>
42846280183517070527831839425882145521227251250327<br>
55121603546981200581762165212827652751691296897789<br>
32238195734329339946437501907836945765883352399886<br>
75506164965184775180738168837861091527357929701337<br>
62177842752192623401942399639168044983993173312731<br>
32924185707147349566916674687634660915035914677504<br>
99518671430235219628894890102423325116913619626622<br>
73267460800591547471830798392868535206946944540724<br>
76841822524674417161514036427982273348055556214818<br>
97142617910342598647204516893989422179826088076852<br>
87783646182799346313767754307809363333018982642090<br>
10848802521674670883215120185883543223812876952786<br>
71329612474782464538636993009049310363619763878039<br>
62184073572399794223406235393808339651327408011116<br>
66627891981488087797941876876144230030984490851411<br>
60661826293682836764744779239180335110989069790714<br>
85786944089552990653640447425576083659976645795096<br>
66024396409905389607120198219976047599490197230297<br>
64913982680032973156037120041377903785566085089252<br>
16730939319872750275468906903707539413042652315011<br>
94809377245048795150954100921645863754710598436791<br>
78639167021187492431995700641917969777599028300699<br>
15368713711936614952811305876380278410754449733078<br>
40789923115535562561142322423255033685442488917353<br>
44889911501440648020369068063960672322193204149535<br>
41503128880339536053299340368006977710650566631954<br>
81234880673210146739058568557934581403627822703280<br>
82616570773948327592232845941706525094512325230608<br>
22918802058777319719839450180888072429661980811197<br>
77158542502016545090413245809786882778948721859617<br>
72107838435069186155435662884062257473692284509516<br>
20849603980134001723930671666823555245252804609722<br>
53503534226472524250874054075591789781264330331690<br>
</div>
# --hints--
`largeSum(testNums)` は数値を返す必要があります。
```js
assert(typeof largeSum(testNums) === 'number');
```
`largeSum(testNums)` は8348422521 を返す必要があります。
```js
assert.strictEqual(largeSum(testNums), 8348422521);
```
`largeSum(fiftyDigitNums)` は 5537376230 を返す必要があります。
```js
assert.strictEqual(largeSum(fiftyDigitNums), 5537376230);
```
# --seed--
## --before-user-code--
```js
const fiftyDigitNums = [
'37107287533902102798797998220837590246510135740250',
'46376937677490009712648124896970078050417018260538',
'74324986199524741059474233309513058123726617309629',
'91942213363574161572522430563301811072406154908250',
'23067588207539346171171980310421047513778063246676',
'89261670696623633820136378418383684178734361726757',
'28112879812849979408065481931592621691275889832738',
'44274228917432520321923589422876796487670272189318',
'47451445736001306439091167216856844588711603153276',
'70386486105843025439939619828917593665686757934951',
'62176457141856560629502157223196586755079324193331',
'64906352462741904929101432445813822663347944758178',
'92575867718337217661963751590579239728245598838407',
'58203565325359399008402633568948830189458628227828',
'80181199384826282014278194139940567587151170094390',
'35398664372827112653829987240784473053190104293586',
'86515506006295864861532075273371959191420517255829',
'71693888707715466499115593487603532921714970056938',
'54370070576826684624621495650076471787294438377604',
'53282654108756828443191190634694037855217779295145',
'36123272525000296071075082563815656710885258350721',
'45876576172410976447339110607218265236877223636045',
'17423706905851860660448207621209813287860733969412',
'81142660418086830619328460811191061556940512689692',
'51934325451728388641918047049293215058642563049483',
'62467221648435076201727918039944693004732956340691',
'15732444386908125794514089057706229429197107928209',
'55037687525678773091862540744969844508330393682126',
'18336384825330154686196124348767681297534375946515',
'80386287592878490201521685554828717201219257766954',
'78182833757993103614740356856449095527097864797581',
'16726320100436897842553539920931837441497806860984',
'48403098129077791799088218795327364475675590848030',
'87086987551392711854517078544161852424320693150332',
'59959406895756536782107074926966537676326235447210',
'69793950679652694742597709739166693763042633987085',
'41052684708299085211399427365734116182760315001271',
'65378607361501080857009149939512557028198746004375',
'35829035317434717326932123578154982629742552737307',
'94953759765105305946966067683156574377167401875275',
'88902802571733229619176668713819931811048770190271',
'25267680276078003013678680992525463401061632866526',
'36270218540497705585629946580636237993140746255962',
'24074486908231174977792365466257246923322810917141',
'91430288197103288597806669760892938638285025333403',
'34413065578016127815921815005561868836468420090470',
'23053081172816430487623791969842487255036638784583',
'11487696932154902810424020138335124462181441773470',
'63783299490636259666498587618221225225512486764533',
'67720186971698544312419572409913959008952310058822',
'95548255300263520781532296796249481641953868218774',
'76085327132285723110424803456124867697064507995236',
'37774242535411291684276865538926205024910326572967',
'23701913275725675285653248258265463092207058596522',
'29798860272258331913126375147341994889534765745501',
'18495701454879288984856827726077713721403798879715',
'38298203783031473527721580348144513491373226651381',
'34829543829199918180278916522431027392251122869539',
'40957953066405232632538044100059654939159879593635',
'29746152185502371307642255121183693803580388584903',
'41698116222072977186158236678424689157993532961922',
'62467957194401269043877107275048102390895523597457',
'23189706772547915061505504953922979530901129967519',
'86188088225875314529584099251203829009407770775672',
'11306739708304724483816533873502340845647058077308',
'82959174767140363198008187129011875491310547126581',
'97623331044818386269515456334926366572897563400500',
'42846280183517070527831839425882145521227251250327',
'55121603546981200581762165212827652751691296897789',
'32238195734329339946437501907836945765883352399886',
'75506164965184775180738168837861091527357929701337',
'62177842752192623401942399639168044983993173312731',
'32924185707147349566916674687634660915035914677504',
'99518671430235219628894890102423325116913619626622',
'73267460800591547471830798392868535206946944540724',
'76841822524674417161514036427982273348055556214818',
'97142617910342598647204516893989422179826088076852',
'87783646182799346313767754307809363333018982642090',
'10848802521674670883215120185883543223812876952786',
'71329612474782464538636993009049310363619763878039',
'62184073572399794223406235393808339651327408011116',
'66627891981488087797941876876144230030984490851411',
'60661826293682836764744779239180335110989069790714',
'85786944089552990653640447425576083659976645795096',
'66024396409905389607120198219976047599490197230297',
'64913982680032973156037120041377903785566085089252',
'16730939319872750275468906903707539413042652315011',
'94809377245048795150954100921645863754710598436791',
'78639167021187492431995700641917969777599028300699',
'15368713711936614952811305876380278410754449733078',
'40789923115535562561142322423255033685442488917353',
'44889911501440648020369068063960672322193204149535',
'41503128880339536053299340368006977710650566631954',
'81234880673210146739058568557934581403627822703280',
'82616570773948327592232845941706525094512325230608',
'22918802058777319719839450180888072429661980811197',
'77158542502016545090413245809786882778948721859617',
'72107838435069186155435662884062257473692284509516',
'20849603980134001723930671666823555245252804609722',
'53503534226472524250874054075591789781264330331690'
];
const testNums = [
'37107287533902102798797998220837590246510135740250',
'46376937677490009712648124896970078050417018260538'
];
```
## --seed-contents--
```js
function largeSum(arr) {
return true;
}
// Only change code above this line
const testNums = [
'37107287533902102798797998220837590246510135740250',
'46376937677490009712648124896970078050417018260538'
];
largeSum(testNums);
```
# --solutions--
```js
function largeSum(arr) {
let sum = 0;
arr.forEach(function(num) {
sum += parseInt(num, 10);
});
sum = sum.toString(10);
sum = sum.substr(0, 1) + sum.substr(2);
let firstTen = sum.slice(0, 10);
return parseInt(firstTen, 10);
}
```

View File

@ -0,0 +1,46 @@
---
id: 5900f3ee1000cf542c50ff00
title: '問題 130: 素数レピュニットの性質を持つ合成数'
challengeType: 5
forumTopicId: 301758
dashedName: problem-130-composites-with-prime-repunit-property
---
# --description--
1 のみで構成される数はレピュニット数と呼ばれます。 ここでは、長さ $k$ のレピュニット数を $R(k)$ と定義します。例えば、$R(6) = 111111$ です。
$n$ を正の整数とし、$GCD(n, 10) = 1$ が与えられる場合、$R(k)$ が $n$ で割り切れるような値 $k$ が必ず存在することを証明できます。また、そのような $k$ の最小値を $A(n)$ とします。例えば、$A(7) = 6$, $A(41) = 5$ です。
すべての素数 $p > 5$ について、$p 1$ は $A(p)$ で割り切れるとします。 例えば、$p = 41 のとき、A(41) = 5$ であり、40 は 5 で割り切れます。
しかし、これが当てはまる合成数もまれに存在し、最初の 5 例は 91, 259, 451, 481, 703 です。
$GCD(n, 10) = 1$ であり、$n 1$ が $A(n)$ で割り切れるような合成数 $n$ について、その最初の 25 個の総和を求めなさい。
# --hints--
`compositeRepunit()``149253` を返す必要があります。
```js
assert.strictEqual(compositeRepunit(), 149253);
```
# --seed--
## --seed-contents--
```js
function compositeRepunit() {
return true;
}
compositeRepunit();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3ef1000cf542c50ff02
title: '問題 131: 素数と立方数の関係'
challengeType: 5
forumTopicId: 301759
dashedName: problem-131-prime-cube-partnership
---
# --description--
一部の素数 $p$ に対して、$n^3 + n^{2}p$ が立方数になるような正の整数 $n$ が 3 つ存在します。
例えば、$p = 19,\\ 8^3 + 8^2 × 19 = {12}^3$ です。
最も驚くべきことは、この性質を持つ各素数に対して $n$ の値が一意であることです。 このような性質を持つ 100 未満の素数は 4 つしかありません。
この驚くべき性質を持つ 100 万未満の素数はいくつありますか。
# --hints--
`primeCubePartnership()``173` を返す必要があります。
```js
assert.strictEqual(primeCubePartnership(), 173);
```
# --seed--
## --seed-contents--
```js
function primeCubePartnership() {
return true;
}
primeCubePartnership();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,42 @@
---
id: 5900f3f11000cf542c50ff03
title: '問題 132: 巨大なレピュニット数の因数'
challengeType: 5
forumTopicId: 301760
dashedName: problem-132-large-repunit-factors
---
# --description--
1 のみで構成される数はレピュニット数と呼ばれます。 ここでは、長さ $k$ のレピュニット数を $R(k)$ とします。
例えば、$R(10) = 1111111111 = 11 × 41 × 271 × 9091$ で、これらの素因数の和は 9414 です。
$R({10}^9)$ の最初の 40 個の素因数の和を求めなさい。
# --hints--
`largeRepunitFactors()``843296` を返す必要があります。
```js
assert.strictEqual(largeRepunitFactors(), 843296);
```
# --seed--
## --seed-contents--
```js
function largeRepunitFactors() {
return true;
}
largeRepunitFactors();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3f21000cf542c50ff04
title: '問題 133: レピュニット数の非因数'
challengeType: 5
forumTopicId: 301761
dashedName: problem-133-repunit-nonfactors
---
# --description--
1 のみで構成される数はレピュニット数と呼ばれます。 ここでは、長さ $k$ のレピュニット数を $R(k)$ とします。例えば、$R(6) = 111111$ です。
$R({10}^n)$ で表されるレピュニット数について考えます。
$R(10)$, $R(100)$, $R(1000)$ はいずれも 17 で割り切れませんが、$R(10000)$ は 17 で割り切れます。 しかし、$R({10}^n)$ が 19 で割り切れるような n の値は存在しません。 意外にも、$R({10}^n)$ の因数になり得る 100 未満の素数は 11, 17, 41, 73 の 4 つだけです。
$R({10}^n)$ の因数になり得ない 10 万未満の素数の総和を求めなさい。
# --hints--
`repunitNonfactors()``453647705` を返す必要があります。
```js
assert.strictEqual(repunitNonfactors(), 453647705);
```
# --seed--
## --seed-contents--
```js
function repunitNonfactors() {
return true;
}
repunitNonfactors();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,42 @@
---
id: 5900f3f21000cf542c50ff05
title: '問題 134: 素数ペアのつながり'
challengeType: 5
forumTopicId: 301762
dashedName: problem-134-prime-pair-connection
---
# --description--
連続する素数 $p_1 = 19$ と $p_2 = 23$ について考えます。 1219 は下位の数字が $p_1$ であり、かつ、$p_2$ によって割り切れる最小の数であることを確認できます。
実際、$p_1 = 3$ と $p_2 = 5$ を除くと、連続する素数 ($p_2 > p_1$) のすべてのペアに対して、下位の桁が $p_1$ であり $n$ が$p_2$ で割り切れるような $n$ の値が存在します。 これらの $n$ の最小値を $S$ とします。
$5 ≤ p_1 ≤ 1000000$ のとき、連続する素数の全ペアの $\sum{S}$ を求めなさい。
# --hints--
`primePairConnection()``18613426663617120` を返す必要があります。
```js
assert.strictEqual(primePairConnection(), 18613426663617120);
```
# --seed--
## --seed-contents--
```js
function primePairConnection() {
return true;
}
primePairConnection();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3f31000cf542c50ff06
title: '問題 135: 同一の差違'
challengeType: 5
forumTopicId: 301763
dashedName: problem-135-same-differences
---
# --description--
正の整数 $x$, $y$, $z$ が等差数列の連続項であるとき、式 $x^2 y^2 z^2 = n$ がちょうど 2 つの解を持つような最小の正の整数 $n$ は、$n = 27$ です。
$$34^2 27^2 20^2 = 12^2 9^2 6^2 = 27$$
$n = 1155$ は、ちょうど 10 個の解を持つ最小値であることが分かります。
相異なる解をちょうど 10 個持つ 100 万未満 の$n$ の値はいくつありますか。
# --hints--
`sameDifferences()``4989` を返す必要があります。
```js
assert.strictEqual(sameDifferences(), 4989);
```
# --seed--
## --seed-contents--
```js
function sameDifferences() {
return true;
}
sameDifferences();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,44 @@
---
id: 5900f3f51000cf542c50ff07
title: '問題 136: 単体の差違'
challengeType: 5
forumTopicId: 301764
dashedName: problem-136-singleton-difference
---
# --description--
正の整数 $x$, $y$, $z$ は等差数列の連続項です。 $n$ を正の整数とすると、式 $x^2 y^2 z^2 = n$ は、$n = 20$ のときちょうど 1 つの解を持ちます。
$$13^2 10^2 7^2 = 20$$
実は、この式の解が 1 つのみになるような $n$ の値は 100 未満で 25 個あります。
この等式の解がちょうど 1 つになるような、5000 万未満 の $n$ の値はいくつありますか。
# --hints--
`singletonDifference()``2544559` を返す必要があります。
```js
assert.strictEqual(singletonDifference(), 2544559);
```
# --seed--
## --seed-contents--
```js
function singletonDifference() {
return true;
}
singletonDifference();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,58 @@
---
id: 5900f3f51000cf542c50ff08
title: '問題 137: フィボナッチ金塊'
challengeType: 5
forumTopicId: 301765
dashedName: problem-137-fibonacci-golden-nuggets
---
# --description--
無限多項式級数 $A_{F}(x) = xF_1 + x^2F_2 + x^3F_3 + \ldots$ について考えます。ここで、$F_k$ はフィボナッチ数列 $1, 1, 2, 3, 5, 8, \ldots$ (すなわち $F_k = F_{k 1} + F_{k 2}, F_1 = 1$, $F_2 = 1$) の第 $k$ 項です。
この問題では、$A_{F}(x)$ が正の整数となるような $x$ の値に注目します。
驚くべきことに、次の式が成り立ちます。
$$\begin{align} A_F(\frac{1}{2}) & = (\frac{1}{2}) × 1 + {(\frac{1}{2})}^2 × 1 + {(\frac{1}{2})}^3 × 2 + {(\frac{1}{2})}^4 × 3 + {(\frac{1}{2})}^5 × 5 + \cdots \\\\ & = \frac{1}{2} + \frac{1}{4} + \frac{2}{8} + \frac{3}{16} + \frac{5}{32} + \cdots \\\\ & = 2 \end{align}$$
最初の 5 つの自然数に対応する $x$ の値を下表に示します。
| $x$ | $A_F(x)$ |
| --------------------------- | -------- |
| $\sqrt{2} 1$ | $1$ |
| $\frac{1}{2}$ | $2$ |
| $\frac{\sqrt{13} 2}{3}$ | $3$ |
| $\frac{\sqrt{89} 5}{8}$ | $4$ |
| $\frac{\sqrt{34} 3}{5}$ | $5$ |
$x$ が有理数である $A_F(x)$ の値は次第にまれになるので、それを「金塊」と呼ぶことにします。例えば、10 番目の金塊は 74049690 です。
15 番目の金塊を求めなさい。
# --hints--
`goldenNugget()``1120149658760` を返す必要があります。
```js
assert.strictEqual(goldenNugget(), 1120149658760);
```
# --seed--
## --seed-contents--
```js
function goldenNugget() {
return true;
}
goldenNugget();
```
# --solutions--
```js
// solution required
```

View File

@ -0,0 +1,46 @@
---
id: 5900f3f61000cf542c50ff09
title: '問題 138: 特殊な二等辺三角形'
challengeType: 5
forumTopicId: 301766
dashedName: problem-138-special-isosceles-triangles
---
# --description--
底辺の長さが $b = 16$、2 本の等辺の長さが $L = 17$ の二等辺三角形を考えます。
<img class="img-responsive center-block" alt="辺 L (2 本の等辺)、底辺 b、および、三角形の底辺から 2 本の辺 L の間の角までの長さ h を持つ二等辺三角形" src="https://cdn.freecodecamp.org/curriculum/project-euler/special-isosceles-triangles.png" style="background-color: white; padding: 10px;" />
ピタゴラスの定理を使えば、三角形の高さは $h = \sqrt{{17}^2 8^2} = 15$ で、底辺の長さより 1 短いことが分かります。
$b = 272$, $L = 305$ のとき、$h = 273$ であり、高さが底辺の長さより 1 長くなります。これは、$h=b±1$ という性質を持つ 2 番目に小さい二等辺三角形です。
$h = b ± 1$ を満たし、$b$ と $L$ が正の整数であるような、12 個の最小の二等辺三角形に対する $\sum{L}$ を求めなさい。
# --hints--
`isoscelesTriangles()``1118049290473932` を返す必要があります。
```js
assert.strictEqual(isoscelesTriangles(), 1118049290473932);
```
# --seed--
## --seed-contents--
```js
function isoscelesTriangles() {
return true;
}
isoscelesTriangles();
```
# --solutions--
```js
// solution required
```

Some files were not shown because too many files have changed in this diff Show More