JavaScriptで解くアルファベット軍団の戦い問題:爆弾による勝敗判定
問題の概要
2つのアルファベット軍団が戦場で対決する状況を想像してください。両チームの兵士とそれぞれの重み(ウェイト)は次の表の通りです。
チームA
| 兵士 | 重み |
|---|---|
| A | 1 |
| B | 2 |
| C | 3 |
| D | 4 |
チームB
| 兵士 | 重み |
|---|---|
| W | 1 |
| X | 2 |
| Y | 3 |
| Z | 4 |
兵士のほかに、戦場には「!」で表される爆弾も配置されています。爆弾が爆発すると、その左右に隣接する位置にいた兵士は消滅します。
たとえば「A!BC」の場合、爆弾の左隣の「A」と右隣の「B」が倒され、結果は「C」になります。また「!!CC!!」の場合は、すべての「C」が爆弾に隣接しているため、結果は空文字列になります。
今回作成する関数の役割は、戦場のすべての爆弾が爆発した後、どちらのチームが勝利するのか、それとも両チームの合計重みが等しく引き分けになるのかを判定することです。
たとえば、関数への入力が次の場合を考えます。
入力
const str = '!WX!YZ!DC!BA!';
出力
const output = 'Tie';
出力の説明
すべての爆弾が爆発した後、両チームの合計スコアが同じになるため、結果は引き分け(Tie)となります。
サンプルコード
以下が実際のコードです。
const str = '!WX!YZ!DC!BA!';
const stringFight = (str = '') => {
const map = {
'D': 4, 'C': 3, 'B': 2, 'A': 1,
'Z': -4, 'Y': -3, 'X': -2, 'W': -1
};
const survivors = [];
const chars = str.split('');
for(let i = 0; i < chars.length; i++){
if(chars[i-1] !== '!' && chars[i] !== '!' && chars[i+1] !== '!'){
survivors.push(chars[i]);
}
}
const sum = survivors.reduce((acc, ch) => acc + (map[ch] || 0), 0);
if(sum < 0){
return 'Team B';
} else if(sum > 0){
return 'Team A';
} else {
return 'Tie';
}
};
console.log(stringFight(str));
出力
Tie
コードの解説
このコードの処理の流れは以下の通りです。
- 重みマップの定義: チームAの兵士(A〜D)には正の値、チームBの兵士(W〜Z)には負の値を割り当てます。これにより、最終的な合計値の符号だけで勝敗を判定できるようになります。
- 生存者の抽出: 文字列を1文字ずつ走査し、自分自身・左隣・右隣のいずれにも爆弾「!」が存在しない文字だけを新しい配列に追加します。これにより、爆発の影響を受けた兵士が自動的に除外されます。
- 合計値による判定: 生存した兵士の重みを合計し、負であれば「Team B」、正であれば「Team A」、0であれば「Tie」を返します。
なお、元のコードには条件分岐が重複して記述されている箇所がありましたが、上記のコードではロジックを整理し、変数名もわかりやすいものに改善しています。この実装の計算量は文字列の長さを n とすると O(n) であり、非常に効率的です。
-
JavaScriptのconst宣言とは?再代入できない変数の基本と使い方を解説
JavaScriptのconst宣言は、値を再代入することも後から再宣言することもできない変数を作成するための構文です。constはES2015(ES6)で導入されました。 const宣言の主な特徴 一度値を代入すると、別の値に再代入することはできません。 同じ名前の変数を同じスコープ内で再宣言するとエラーになります。 宣言時に必ず初期値を代入する必要があります。 ブロックスコープ({}内でのみ有効)を持ちます。 それでは、JavaScriptにおけるconst宣言の実際のコードを見ていきましょう。 サンプルコード <!DOCTYPE html> <html>
-
JavaScriptのconstとletの違いを徹底解説!ブロックスコープ変数の基本と使い方
JavaScriptにおけるconstとletの基本const と let は、ES2015(ES6)で導入された変数宣言用のキーワードです。どちらもブロックスコープ(波括弧 { } で囲まれた範囲)に対応しているのが特徴で、関数スコープしか持たなかった従来の var とは異なる挙動を示します。両者の大きな違いは再代入の可否です。letで宣言した変数は後から何度でも値を再代入できますが、constで宣言した変数は再代入しようとするとエラー(TypeError)が発生します。letとconstの主な違い項目letconst再代入可能不可(エラー発生)スコープブロックスコープブロックスコープ宣言時