2017-03-20 11 views
2

私は特定の方法でシャッフルする必要がある文字列 "ABCDEFGHIJKLMN"を持っています。これを行うために、すべての文字が完了するまで、下から上 - >上 - >左 - >右(たとえば、列あたり4文字)の文字を順番に書きます。最後の列が完了していない場合は、空のスペースが下部にある必要があります(これは非常に重要です)。そのような:縦反転パターンで文字をシャッフルする方法は?

DHLN
CGKM
BFJ
AEI

我々はテキストを読むようshuffleは、左の列で、文字のブロックを読んで新しい文字列を生成することによって達成される - >右:

"DHLNCGKMBFJAEI" の列はありません

例完全(word.size%column_height!= 0)は物事をかなり複雑にします。

私はいくつかの解決策を思いつきましたが、この問題をより簡潔に(すなわち、読みやすく、読みやすく)、よりエレガントにする方法があるかどうかはわかりません。私の解決策は、最終的な不完全な列を扱うためのコードの醜い別個のブロックを持っているか、複雑すぎるように思える。

私の質問は、もっとうまくできますか?

あなたがスポイラーを必要とせず、あなた自身でそれを見つけようとするならば、今読んでおいてください。あなたは、私がこれまでにいじったものから仕事をしたい場合は、コードの作業部分は

var result = ""; 
 
var str = "ABCDEFGHIJKLMN"; 
 
var nr_rows = 4; 
 
var current_row = 4; 
 
var columns = Math.floor(str.length/nr_rows); 
 
var modulus_table = str.length % nr_rows; 
 
var modulus_position = -1; 
 
for (var i = 0; i < nr_rows; i++) { 
 
    for (var j = 0; j < columns; j++) { 
 
    result += str[current_row + j * nr_rows - 1]; 
 
    } 
 
    if (modulus_table > 0) { 
 
    result += str[str.length + modulus_position]; 
 
    modulus_table--; 
 
    modulus_position--; 
 
    } 
 
    current_row--; 
 
} 
 
console.log(result);

がで正しく、次の例では、それを各文字をループ置くだろう配列に移るです行列のような配列ですが、うまくいきません。配列を別の方法で作成する必要があります。この問題の別の例については、How to create empty 2d array in javascript?を参照してください。これはまた、最後の不完全な列の最後の文字を上端ではなく下端に合わせて修正するためには醜いハッキングが必要です。

var result = [[],[]]; 
 
var str = "ABCDEFGHIJKLMN"; 
 
var nr_rows = 4; 
 
var row = nr_rows - 1; 
 
var column = 0; 
 
for (var i = 0; i < str.length; i++) { 
 
    result[row][column] = str[i]; 
 
    row--; 
 
    if (row < 0) { 
 
    row = nr_rows; 
 
    column++; 
 
    } 
 
} 
 
console.log(result);

この最後の方法は、フルマトリクスアレイを行くが、それは3つの異なる方向に配列をループする必要があるため、それはすぐに、複雑になります。最初に、間違った場所に文字を含むダミー配列を作成しますが、 '未定義'の位置は空のままにする必要があります。これは、読み取り方向から90度回転した配列を読み込むことによって実現されます。 この最初の手順がないと、空の位置が上部の代わりに下部に積み重ねられます。

「未定義」値を使用して、行列の任意の穴をスキップして、カラクタを正しい場所に書き直すには、2番目のパスが必要です。このチェックはすべての位置に対して行われ、不完全な最後の行を処理するためのコードブロックはありません。

3回目のパスで最後のシャッフルされた文字列が形成されます。これはあまりにも複雑で紛らわしいようです。

// matrix populated top->bottom and left->right 
 
// with the characters in the wrong place 
 
// but the undefined postions in the correct place of the empty positions 
 
var matrix = []; 
 
var str = "ABCDEFGHIJKLMN"; 
 
var rows = 4; 
 
var columns = Math.ceil(str.length/rows); 
 
var k = 0; 
 
for (var i = 0; i < rows; i++) { 
 
    matrix[i] = []; 
 
    for (var j = columns - 1; j >= 0; j--) { 
 
    matrix[i][j] = str[k]; 
 
    k++; 
 
    } 
 
} 
 

 
// populate the matrix with the chars in the correct place and the 'undefined' positions left empty 
 
var k = 0; 
 
for (var i = 0; i < rows; i++) { 
 
    for (var j = 0; j < columns; j++) { 
 
    if (matrix[i][j] != undefined) { 
 
     matrix[i][j] = str[k]; 
 
     k++; 
 
    } 
 
    } 
 
} 
 

 
// read matrix in correct direction and send to string, skipping empty positions 
 
var result = ""; 
 
for (var j = columns - 1; j >= 0; j--) { 
 
    for (var i = 0; i < rows; i++) { 
 
    if (matrix[i][j] != undefined) { 
 
     result += matrix[i][j]; 
 
    } 
 
    } 
 
} 
 
console.log(result);

+0

"*最後の行が完了していない場合... *" "最後の列... *場合*" でなければなりません。 – RobG

+0

何が問題なのですか? – guest271314

+0

読みやすく(標準ライブラリと式を使用できます):操作を複数の標準マトリックス操作に分割します。 1.文字列を4xn行列に、2. Transpose行列を、3. Horizo​​ntallyミラー/フリップ行列を、4.最後の列をシフトします。5.行列を1x(mxn)文字列に変更します。 –

答えて

0

正しく質問を解釈する場合は、に、文字列の文字で配列を移入するforループ、String.prototype.slice()を使用することができます。再帰関数内でArray.prototype.pop()を使用して、各配列.length0になるまで配列の最後の要素を取得します。親配列の.lengthがで設定された、2されたらは3.length4を有する要素を含む配列の配列を設定するforループ、String.prototype.slice()を使用するか、またはでき上下反転文字列から配列

[ 
    ["D","H","L","N"], 
    ["C","G","K","M"], 
    ["B","F","J"], 
    ["A","E","I"] 
    ] 

を作成する

四つの要素

var str = "ABCDEFGHIJKLMN"; 
 

 
function fnVerticalInvert(str, arr, res) { 
 

 
    if (!arr && !res) { 
 
    arr = []; res = ""; 
 
    } 
 

 
    if (str) { 
 
    for (var i = 0; i < str.length; i += 4) { 
 
     arr.push([].slice.call(str.slice(i, i + 4))); 
 
    } 
 
    } 
 

 
    for (var i = 0; i < arr.length; i++) { 
 
    if (arr[i].length) { 
 
     res += arr[i].pop() 
 
    } 
 
    } 
 

 
    if (arr.some(function(curr) {return curr.length})) 
 
    return fnVerticalInvert(null, arr, res); 
 

 
    for (var i = 0, l = 4, j = 0, n = l - 1, k; i < l; i++, j += l) { 
 
    if (i === l/2) k = j; 
 
    arr[i] = [].slice.call(res.slice(!k ? j : k, !k ? j + l : k + n)); 
 
    if (k) k += n; 
 
    } 
 

 
    return {str: res, arr:arr}; 
 

 
}; 
 

 
var res = fnVerticalInvert(str); 
 

 
console.log(res);
を含む二つの配列

0

文字列を返す場合は、中間結果で配列を使用する必要がない場合は、その理由がわかりません。次のコードでは配列を1つ減らすことができますが、をsplitに、配列をに、をループするのが便利です。

考え方は、列がいっぱいになるまで下から上に文字列を塗りつぶし、割り当てが不足するまで各列の下から追加し続けます。塗りつぶしを開始する行は、残っている文字の数とそこにある行の数に基づいています。

文字列を作成するのではなく、配列を作成することができますが、文字列を生成するにはの複数の結合が必要です

また、すべての文字に対してスロットが不十分なため、3x3の「マトリックス」を使用して10以上の9文字を使用した結果が得られます(最後の例を参照)。

function verticalShuffle(s, rows, cols) { 
 
    var result = ['']; 
 
    s = s.split(''); 
 

 
    while (s.length && result[0].length < cols) { 
 
    for (var i = (rows < s.length? rows : s.length) -1 ; i>=0; i--) { 
 
     if (!result[i]) result[i] = ''; 
 
     result[i] += s.splice(0,1)[0] || ''; 
 
    } 
 
    } 
 
    return result.join(''); 
 
} 
 

 
var s = 'ABCDEFGHIJKLMN'; 
 

 
console.log(verticalShuffle(s, 4, 4)); // DHLNCGKMBFJAEI 
 
console.log(verticalShuffle(s, 6, 3)); // FLNEKMDJCIBHAG 
 
// Only use 9 characters 
 
console.log(verticalShuffle(s, 3, 3)); // CFIBEHADG

これは、任意のブラウザで実行されます平野ED3機能を使用しています。私はそれをECMAScript 2015以降のホストに制限するという点は見当たりません。

0

アレイを列グループに分割/逆変換して行に変換するだけの場合はどうなりますか?

const result = str.match(/.{1,4}/g) // split string into groups of 4 
    .map(i => i.split('').reverse())  // reverse each group (bottom to top, and solves the last col issue) 
    .reduce((res, col) => {    // reduce the groups into rows 
    col.forEach((c, i) => res[i] += c) // concat each string char to the right row 
    return res 
    }, ['','','',''])     // initialise empty strings per row 
    .join('')       // join the rows up 

フィドルhere

関連する問題