rotateInPlace()

Циклически повернуть массив вправо на заданное число (возможно отрицательное!) элементов.

by l_gordienkova

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.4.5/mocha.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.4.5/mocha.min.css">
<div id="mocha">
</div>
<script>
  mocha.setup('bdd');
  var assert = chai.assert;
  var expect = chai.expect;
</script>
<script>

  describe("rotate", function() {
    before(function () {
      chai.config.includeStack = false;
    });
    describe('формат', function(){
      it("объявлена", function() {
        assert.isFunction(window.rotateInPlace);
      });
      it("принимает 2 аргумента", function() {
        assert.equal(rotateInPlace.length, 2);
      });
    });
    
    describe('проверки', function(){
    	function suite(name, length, shift){
      	var src = Array.apply(0, new Array(length)).map(e => ~~(Math.random() * 100));
        console.log(src);
        var input = src.slice(), output;
        try{
        	output = rotateInPlace(input, shift);
          describe(name, function(){
            it('новый массив не создан', function(){
              assert.strictEqual(output, input);
            });
            it('длина прежняя', function(){
              assert.equal(output.length, src.length);
            });
            if(length)
              it('содержимое сдвинуто', function(){
                const l = src.length;
                assert.ok(output.every((e, i) => e === src[((i + shift) % l + l) % l]));
              });
          })
        } catch(e) {
        	it('выполняется', function(){
          	throw e;
          })
        }
      }
      suite("пустой массив без сдвига", 0, 0);
      suite("пустой массив со сдвигом", 0, 2);
      suite("массив без сдвига", 5, 0);
      suite("сдвиг вправо на 1", 5, 1);
      suite("сдвиг влево на 1", 5, -1);
      suite("сдвиг на половину длины вправо", 50, 25);
      suite("сдвиг на половину длины влево", 50, -25);
     ...

JavaScript

function rotateInPlace(array, n){
  var length = array.length;
if(Math.abs(n) > length) n = findN(n,length); 

var a = [];
for(var i = 0; i < array.length; i++){
    a[i] = array[i];
}

if(n>0){
for( var i = 0; i < length-n;i++){
    array[i] = array[i+n];
}
var k = 0;
for( var i = length-n; i < length ; i++){
    array[i] = a[k];
    k++;
}}

if(n<0){
n = -n;
for( var i = 0; i < length-n;i++){
    array[i+n] = a[i];
}
var k = 0;
for( var i = length-n; i < length ; i++){
    array[k] = a[i];
    k++;
}
}

return array; 
}

function findN(n,length){
   N = n % length;
   if(N < length)
    return N;
    if(N > length) findN(N,length);
}