JavaScriptのプログラミングスキルを向上させるための問題集を50問作成しました。
以下の問題に取り組んで、基本的な知識から応用まで幅広く学ぶことができます。
答えは下の方に書いておきます。
問題
基本的な問題
- Hello World: "Hello, World!" をコンソールに出力する関数を作成してください。
- 加算: 2つの数を引数として受け取り、その合計を返す関数を作成してください。
- 偶数か奇数か: 数値を引数として受け取り、その数が偶数か奇数かを返す関数を作成してください。
- 配列の合計: 数値の配列を引数として受け取り、その合計を返す関数を作成してください。
- 文字列の逆転: 文字列を引数として受け取り、その逆転文字列を返す関数を作成してください。
中級の問題
- 最大値の取得: 数値の配列を引数として受け取り、その最大値を返す関数を作成してください。
- フィボナッチ数列: n 番目のフィボナッチ数を返す関数を作成してください。
- 素数判定: 数値を引数として受け取り、その数が素数かどうかを判定する関数を作成してください。
- 配列の平均値: 数値の配列を引数として受け取り、その平均値を返す関数を作成してください。
- 文字列の大文字変換: 文字列を引数として受け取り、全て大文字に変換した文字列を返す関数を作成してください。
上級の問題
- アナグラム判定: 2つの文字列を引数として受け取り、それらがアナグラムかどうかを判定する関数を作成してください。
- 配列の重複削除: 配列を引数として受け取り、重複を削除した新しい配列を返す関数を作成してください。
- 2つの配列の共通要素: 2つの配列を引数として受け取り、共通する要素を含む配列を返す関数を作成してください。
- 配列のソート: 数値の配列を引数として受け取り、昇順にソートした配列を返す関数を作成してください。
- 指定された文字のカウント: 文字列と文字を引数として受け取り、その文字が文字列内に何回出現するかをカウントする関数を作成してください。
応用問題
- カンマ区切りの文字列を配列に変換: カンマ区切りの文字列を引数として受け取り、それを配列に変換する関数を作成してください。
- 配列内の最大値と最小値を取得: 数値の配列を引数として受け取り、最大値と最小値を含むオブジェクトを返す関数を作成してください。
- 文字列の単語数をカウント: 文字列を引数として受け取り、その文字列内の単語数を返す関数を作成してください。
- 指定された要素のインデックスを取得: 配列と要素を引数として受け取り、その要素が配列内に存在する場合はインデックスを返し、存在しない場合は-1を返す関数を作成してください。
- 特定の条件を満たす配列の要素を取得: 配列と条件を引数として受け取り、その条件を満たす要素のみを含む新しい配列を返す関数を作成してください。
高度な問題
- JSONのキーの一覧を取得: JSONオブジェクトを引数として受け取り、そのキーの一覧を配列で返す関数を作成してください。
- 配列の要素をランダムにシャッフル: 数値の配列を引数として受け取り、ランダムにシャッフルした配列を返す関数を作成してください。
- 二次元配列の転置: 二次元配列を引数として受け取り、その転置行列を返す関数を作成してください。
- オブジェクトのプロパティのコピー: オブジェクトを引数として受け取り、そのプロパティをコピーした新しいオブジェクトを返す関数を作成してください。
- 指定された長さのランダムな文字列を生成: 指定された長さのランダムな文字列を生成する関数を作成してください。
実践的な問題
- ファイルの拡張子を取得: ファイル名を引数として受け取り、そのファイルの拡張子を返す関数を作成してください。
- 数値の配列を指定された桁数でフォーマット: 数値の配列を引数として受け取り、指定された桁数でゼロパディングした新しい配列を返す関数を作成してください。
- カンマ区切りの数字を数値に変換: カンマ区切りの数字を含む文字列を引数として受け取り、それを数値に変換する関数を作成してください。
- 全ての文字を小文字に変換: 文字列を引数として受け取り、全て小文字に変換した文字列を返す関数を作成してください。
- 文字列の特定の文字を置換: 文字列、置換対象の文字、および置換後の文字を引数として受け取り、指定された文字を置換した新しい文字列を返す関数を作成してください。
上級実践問題
- 指定された文字の位置を取得: 文字列と文字を引数として受け取り、その文字が文字列内で最初に出現する位置を返す関数を作成してください。
- 文字列の重複を削除: 文字列を引数として受け取り、重複する文字を削除した新しい文字列を返す関数を作成してください。
- 配列を指定された数で分割: 配列と分割数を引数として受け取り、指定された数ごとに分割された二次元配列を返す関数を作成してください。
- 文字列の各単語の最初の文字を大文字に変換: 文字列を引数として受け取り、各単語の最初の文字を大文字に変換した文字列を返す関数を作成してください。
- JSONを配列に変換: JSONオブジェクトを引数として受け取り、その値を配列に変換する関数を作成してください。
高度な応用問題
- 指定された範囲の乱数を生成: 指定された範囲(最小値と最大値)内の乱数を生成する関数を作成してください。
- 配列の要素をランダムに選択: 配列を引数として受け取り、その中からランダムに選択された要素を返す関数を作成してください。
- 2つの日付の差を計算: 2つの日付を引数として受け取り、その差(日数)を返す関数を作成してください。
- 文字列のパリンドローム判定: 文字列を引数として受け取り、その文字列がパリンドローム(回文)かどうかを判定する関数を作成してください。
- 配列の要素を指定された回数繰り返す: 配列と繰り返し回数を引数として受け取り、その要素を指定された回数だけ繰り返す新しい配列を返す関数を作成してください。
上級アルゴリズム問題
- 二分探索アルゴリズムの実装: ソートされた数値の配列とターゲットの数を引数として受け取り、二分探索アルゴリズムを使用してターゲットのインデックスを返す関数を作成してください。ターゲットが見つからない場合は-1を返します。
- ハノイの塔アルゴリズムの実装: ハノイの塔の問題を解く関数を作成してください。関数は、ディスクの移動を表す手順を出力します。
- クイックソートアルゴリズムの実装: クイックソートアルゴリズムを使用して、数値の配列をソートする関数を作成してください。
- 深さ優先探索(DFS)の実装: グラフを表す隣接リストとスタートノードを引数として受け取り、深さ優先探索を実行する関数を作成してください。
- 幅優先探索(BFS)の実装: グラフを表す隣接リストとスタートノードを引数として受け取り、幅優先探索を実行する関数を作成してください。
応用アルゴリズム問題
- ダイクストラのアルゴリズムの実装: グラフを表す隣接リストとスタートノードを引数として受け取り、ダイクストラのアルゴリズムを使用して最短経路を計算する関数を作成してください。
- 動的計画法(DP)の実装: フィボナッチ数列を動的計画法を使用して計算する関数を作成してください。
- ナップサック問題の解決: ナップサック問題を解決する関数を作成してください。アイテムの重さと価値、およびナップサックの最大重量を引数として受け取ります。
- 最大公約数(GCD)の計算: 2つの数値を引数として受け取り、最大公約数を計算する関数を作成してください。
- 文字列のパーミュテーションを生成: 文字列を引数として受け取り、そのすべてのパーミュテーションを生成する関数を作成してください。
答え
基本的な問題
Hello World: "Hello, World!" をコンソールに出力する関数を作成してください。
function helloWorld() {
console.log("Hello, World!");
}
加算: 2つの数を引数として受け取り、その合計を返す関数を作成してください。
function add(a, b) {
return a + b;
}
偶数か奇数か: 数値を引数として受け取り、その数が偶数か奇数かを返す関数を作成してください。
function isEven(num) {
return num % 2 === 0 ? "Even" : "Odd";
}
配列の合計: 数値の配列を引数として受け取り、その合計を返す関数を作成してください。
function sumArray(arr) {
return arr.reduce((acc, num) => acc + num, 0);
}
文字列の逆転: 文字列を引数として受け取り、その逆転文字列を返す関数を作成してください。
function reverseString(str) {
return str.split('').reverse().join('');
}
中級の問題
最大値の取得: 数値の配列を引数として受け取り、その最大値を返す関数を作成してください。
function maxArray(arr) {
return Math.max(...arr);
}
フィボナッチ数列: n 番目のフィボナッチ数を返す関数を作成してください。
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
素数判定: 数値を引数として受け取り、その数が素数かどうかを判定する関数を作成してください。
function isPrime(num) {
if (num <= 1) return false;
for (let i = 2; i <= Math.sqrt(num); i++) {
if (num % i === 0) return false;
}
return true;
}
配列の平均値: 数値の配列を引数として受け取り、その平均値を返す関数を作成してください。
function averageArray(arr) {
return sumArray(arr) / arr.length;
}
文字列の大文字変換: 文字列を引数として受け取り、全て大文字に変換した文字列を返す関数を作成してください。
function toUpperCase(str) {
return str.toUpperCase();
}
上級の問題
アナグラム判定: 2つの文字列を引数として受け取り、それらがアナグラムかどうかを判定する関数を作成してください。
function areAnagrams(str1, str2) {
const normalize = str => str.toLowerCase().replace(/[^a-z\d]/g, '').split('').sort().join('');
return normalize(str1) === normalize(str2);
}
配列の重複削除: 配列を引数として受け取り、重複を削除した新しい配列を返す関数を作成してください。
function removeDuplicates(arr) {
return [...new Set(arr)];
}
2つの配列の共通要素: 2つの配列を引数として受け取り、共通する要素を含む配列を返す関数を作成してください。
function commonElements(arr1, arr2) {
return arr1.filter(element => arr2.includes(element));
}
配列のソート: 数値の配列を引数として受け取り、昇順にソートした配列を返す関数を作成してください。
function sortArray(arr) {
return arr.slice().sort((a, b) => a - b);
}
指定された文字のカウント: 文字列と文字を引数として受け取り、その文字が文字列内に何回出現するかをカウントする関数を作成してください。
function countCharacter(str, char) {
return str.split(char).length - 1;
}
応用問題
カンマ区切りの文字列を配列に変換: カンマ区切りの文字列を引数として受け取り、それを配列に変換する関数を作成してください。
function stringToArray(str) {
return str.split(',');
}
配列内の最大値と最小値を取得: 数値の配列を引数として受け取り、最大値と最小値を含むオブジェクトを返す関数を作成してください。
function minMaxArray(arr) {
return {
min: Math.min(...arr),
max: Math.max(...arr)
};
}
文字列の単語数をカウント: 文字列を引数として受け取り、その文字列内の単語数を返す関数を作成してください。
function countWords(str) {
return str.split(' ').filter(word => word.length > 0).length;
}
指定された要素のインデックスを取得: 配列と要素を引数として受け取り、その要素が配列内に存在する場合はインデックスを返し、存在しない場合は-1を返す関数を作成してください。
function findIndex(arr, element) {
return arr.indexOf(element);
}
特定の条件を満たす配列の要素を取得: 配列と条件を引数として受け取り、その条件を満たす要素のみを含む新しい配列を返す関数を作成してください。
function filterArray(arr, condition) {
return arr.filter(condition);
}
高度な問題
JSONのキーの一覧を取得: JSONオブジェクトを引数として受け取り、そのキーの一覧を配列で返す関数を作成してください。
function getJsonKeys(json) {
return Object.keys(json);
}
配列の要素をランダムにシャッフル: 数値の配列を引数として受け取り、ランダムにシャッフルした配列を返す関数を作成してください。
function shuffleArray(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
二次元配列の転置: 二次元配列を引数として受け取り、その転置行列を返す関数を作成してください。
function transposeMatrix(matrix) {
return matrix[0].map((_, colIndex) => matrix.map(row => row[colIndex]));
}
オブジェクトのプロパティのコピー: オブジェクトを引数として受け取り、そのプロパティをコピーした新しいオブジェクトを返す関数を作成してください。
function copyObject(obj) {
return { ...obj };
}
指定された長さのランダムな文字列を生成: 指定された長さのランダムな文字列を生成する関数を作成してください。
実践的な問題
ファイルの拡張子を取得: ファイル名を引数として受け取り、そのファイルの拡張子を返す関数を作成してください。
function getFileExtension(filename) {
return filename.split('.').pop();
}
数値の配列を指定された桁数でフォーマット: 数値の配列を引数として受け取り、指定された桁数でゼロパディングした新しい配列を返す関数を作成してください。
function padNumbers(arr, length) {
return arr.map(num => num.toString().padStart(length, '0'));
}
カンマ区切りの数字を数値に変換: カンマ区切りの数字を含む文字列を引数として受け取り、それを数値に変換する関数を作成してください。
function parseCommaNumber(str) {
return parseFloat(str.replace(/,/g, ''));
}
全ての文字を小文字に変換: 文字列を引数として受け取り、全て小文字に変換した文字列を返す関数を作成してください。
function toLowerCase(str) {
return str.toLowerCase();
}
文字列の特定の文字を置換: 文字列、置換対象の文字、および置換後の文字を引数として受け取り、指定された文字を置換した新しい文字列を返す関数を作成してください。
function replaceCharacter(str, target, replacement) {
return str.split(target).join(replacement);
}
上級実践問題
指定された文字の位置を取得: 文字列と文字を引数として受け取り、その文字が文字列内で最初に出現する位置を返す関数を作成してください。
function findCharacterPosition(str, char) {
return str.indexOf(char);
}
文字列の重複を削除: 文字列を引数として受け取り、重複する文字を削除した新しい文字列を返す関数を作成してください。
function removeDuplicateCharacters(str) {
return Array.from(new Set(str)).join('');
}
配列を指定された数で分割: 配列と分割数を引数として受け取り、指定された数ごとに分割された二次元配列を返す関数を作成してください。
function chunkArray(arr, size) {
let result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}
文字列の各単語の最初の文字を大文字に変換: 文字列を引数として受け取り、各単語の最初の文字を大文字に変換した文字列を返す関数を作成してください。
function capitalizeWords(str) {
return str.replace(/\b\w/g, char => char.toUpperCase());
}
JSONを配列に変換: JSONオブジェクトを引数として受け取り、その値を配列に変換する関数を作成してください。
高度な応用問題
指定された範囲の乱数を生成: 指定された範囲(最小値と最大値)内の乱数を生成する関数を作成してください。
function getRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
配列の要素をランダムに選択: 配列を引数として受け取り、その中からランダムに選択された要素を返す関数を作成してください。
function getRandomElement(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
2つの日付の差を計算: 2つの日付を引数として受け取り、その差(日数)を返す関数を作成してください。
function dateDifference(date1, date2) {
const diffTime = Math.abs(date2 - date1);
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}
文字列のパリンドローム判定: 文字列を引数として受け取り、その文字列がパリンドローム(回文)かどうかを判定する関数を作成してください。
function isPalindrome(str) {
const normalizedStr = str.toLowerCase().replace(/[^a-z0-9]/g, '');
return normalizedStr === normalizedStr.split('').reverse().join('');
}
配列の要素を指定された回数繰り返す: 配列と繰り返し回数を引数として受け取り、その要素を指定された回数だけ繰り返す新しい配列を返す関数を作成してください。
function repeatElements(arr, times) {
return arr.flatMap(element => Array(times).fill(element));
}
上級アルゴリズム問題
二分探索アルゴリズムの実装: ソートされた数値の配列とターゲットの数を引数として受け取り、二分探索アルゴリズムを使用してターゲットのインデックスを返す関数を作成してください。ターゲットが見つからない場合は-1を返します。
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
ハノイの塔アルゴリズムの実装: ハノイの塔の問題を解く関数を作成してください。関数は、ディスクの移動を表す手順を出力します。
function hanoi(n, from, to, aux) {
if (n === 1) {
console.log(`Move disk 1 from ${from} to ${to}`);
return;
}
hanoi(n - 1, from, aux, to);
console.log(`Move disk ${n} from ${from} to ${to}`);
hanoi(n - 1, aux, to, from);
}
// 使用例
hanoi(3, 'A', 'C', 'B');
クイックソートアルゴリズムの実装: クイックソートアルゴリズムを使用して、数値の配列をソートする関数を作成してください。
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
const pivot = arr[Math.floor(arr.length / 2)];
const left = arr.filter(x => x < pivot);
const right = arr.filter(x => x > pivot);
return [...quickSort(left), pivot, ...quickSort(right)];
}
深さ優先探索(DFS)の実装: グラフを表す隣接リストとスタートノードを引数として受け取り、深さ優先探索を実行する関数を作成してください。
function dfs(graph, start) {
const stack = [start];
const visited = new Set();
while (stack.length > 0) {
const node = stack.pop();
if (!visited.has(node)) {
visited.add(node);
console.log(node);
for (const neighbor of graph[node]) {
stack.push(neighbor);
}
}
}
}
// 使用例
const graph = {
A: ['B', 'C'],
B: ['D', 'E'],
C: ['F'],
D: [],
E: ['F'],
F: []
};
dfs(graph, 'A');
幅優先探索(BFS)の実装: グラフを表す隣接リストとスタートノードを引数として受け取り、幅優先探索を実行する関数を作成してください。
function bfs(graph, start) {
const queue = [start];
const visited = new Set();
while (queue.length > 0) {
const node = queue.shift();
if (!visited.has(node)) {
visited.add(node);
console.log(node);
for (const neighbor of graph[node]) {
queue.push(neighbor);
}
}
}
}
// 使用例
const graph = {
A: ['B', 'C'],
B: ['D', 'E'],
C: ['F'],
D: [],
E: ['F'],
F: []
};
bfs(graph, 'A');
応用アルゴリズム問題
ダイクストラのアルゴリズムの実装: グラフを表す隣接リストとスタートノードを引数として受け取り、ダイクストラのアルゴリズムを使用して最短経路を計算する関数を作成してください。
function dijkstra(graph, start) {
const distances = {};
const visited = new Set();
const queue = new PriorityQueue();
for (const node in graph) {
distances[node] = Infinity;
}
distances[start] = 0;
queue.enqueue(start, 0);
while (!queue.isEmpty()) {
const { element: node } = queue.dequeue();
if (!visited.has(node)) {
visited.add(node);
for (const neighbor in graph[node]) {
const distance = graph[node][neighbor];
const totalDistance = distances[node] + distance;
if (totalDistance < distances[neighbor]) {
distances[neighbor] = totalDistance;
queue.enqueue(neighbor, totalDistance);
}
}
}
}
return distances;
}
class PriorityQueue {
constructor() {
this.items = [];
}
enqueue(element, priority) {
const queueElement = { element, priority };
let added = false;
for (let i = 0; i < this.items.length; i++) {
if (queueElement.priority < this.items[i].priority) {
this.items.splice(i, 0, queueElement);
added = true;
break;
}
}
if (!added) {
this.items.push(queueElement);
}
}
dequeue() {
return this.items.shift();
}
isEmpty() {
return this.items.length === 0;
}
}
// 使用例
const graph = {
A: { B: 1, C: 4 },
B: { A: 1, C: 2, D: 5 },
C: { A: 4, B: 2, D: 1 },
D: { B: 5, C: 1 }
};
console.log(dijkstra(graph, 'A'));
動的計画法(DP)の実装: フィボナッチ数列を動的計画法を使用して計算する関数を作成してください。
function fibonacciDP(n) {
const memo = [0, 1];
for (let i = 2; i <= n; i++) {
memo[i] = memo[i - 1] + memo[i - 2];
}
return memo[n];
}
console.log(fibonacciDP(10)); // 55
ナップサック問題の解決: ナップサック問題を解決する関数を作成してください。アイテムの重さと価値、およびナップサックの最大重量を引数として受け取ります。
function knapsack(values, weights, capacity) {
const n = values.length;
const dp = Array.from({ length: n + 1 }, () => Array(capacity + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let w = 0; w <= capacity; w++) {
if (weights[i - 1] <= w) {
dp[i][w] = Math.max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][capacity];
}
// 使用例
const values = [60, 100, 120];
const weights = [10, 20, 30];
const capacity = 50;
console.log(knapsack(values, weights, capacity)); // 220
最大公約数(GCD)の計算: 2つの数値を引数として受け取り、最大公約数を計算する関数を作成してください。
function gcd(a, b) {
while (b !== 0) {
const temp = b;
b = a % b;
a = temp;
}
return a;
}
console.log(gcd(48, 18)); // 6
文字列のパーミュテーションを生成: 文字列を引数として受け取り、そのすべてのパーミュテーションを生成する関数を作成してください。
function permute(str) {
const result = [];
if (str.length === 1) {
return [str];
}
for (let i = 0; i < str.length; i++) {
const char = str[i];
const remainingChars = str.slice(0, i) + str.slice(i + 1);
for (const perm of permute(remainingChars)) {
result.push(char + perm);
}
}
return result;
}
console.log(permute("abc")); // ["abc", "acb", "bac", "bca", "cab", "cba"]
総括
これらの問題を通じて、JavaScriptの基本的な操作から高度なアルゴリズムまで幅広く学ぶことができます。
それぞれの問題に取り組むことで、プログラミングスキルを段階的に向上させることができます。
興味のある問題や難しいと感じる問題に挑戦し、必要に応じてリファレンスやドキュメントを活用してください。