জাভাস্ক্রিপ্টে প্রবেশের অনুমতি?


138

আমি একটি ফাংশন লিখতে চেষ্টা করছি যা নিম্নলিখিতগুলি করে:

  • একটি আর্গুমেন্ট হিসাবে পূর্ণসংখ্যার অ্যারে নেয় (উদাঃ [1,2,3,4])
  • প্রতিটি অনুক্রমের দৈর্ঘ্য 4 এর সাথে [1,2,3,4] এর সমস্ত সম্ভাব্য অনুমতিের একটি অ্যারে তৈরি করে

নীচের ফাংশনটি (আমি এটি অনলাইনে খুঁজে পেয়েছি) এটি একটি আর্গুমেন্ট হিসাবে একটি স্ট্রিং গ্রহণ করে এবং সেই স্ট্রিংয়ের সমস্ত অনুমতিগুলি ফেরত দিয়ে এটি করে

এটিকে পূর্ণসংখ্যার অ্যারের সাথে কাজ করার জন্য এটি কীভাবে পরিবর্তন করতে হবে তা আমি বুঝতে পারি না, (আমি মনে করি যে এর কিছুটি পদ্ধতিতে স্ট্রিংয়ের সাথে পৃথকভাবে কাজ করে তার সাথে কিছু করার আছে তবে আমি নিশ্চিত নই। ..)

var permArr = [], usedChars = [];
function permute(input) {
  var i, ch, chars = input.split("");
  for (i = 0; i < chars.length; i++) {
    ch = chars.splice(i, 1);
    usedChars.push(ch);
    if (chars.length == 0)
      permArr[permArr.length] = usedChars.join("");
    permute(chars.join(""));
    chars.splice(i, 0, ch);
    usedChars.pop();
  }
  return permArr
};

দ্রষ্টব্য: আমি এর ফাংশন রিটার্ন অ্যারে করতে থাকবো পূর্ণসংখ্যার , না একটি অ্যারের স্ট্রিং

জাভাস্ক্রিপ্টে থাকার সমাধানটি আমার সত্যই দরকার। পাইথনে এটি কীভাবে করা যায় তা আমি ইতিমধ্যে খুঁজে পেয়েছি

উত্তর:


106

যদি আপনি লক্ষ্য করেন, কোডটি কোনও ক্রম ছাড়ার আগে অক্ষরগুলিকে প্রকৃতপক্ষে একটি অ্যারেতে বিভক্ত করে, তাই আপনি কেবল যোগদান এবং বিভক্ত ক্রিয়াকলাপ সরিয়ে ফেলুন

var permArr = [],
  usedChars = [];

function permute(input) {
  var i, ch;
  for (i = 0; i < input.length; i++) {
    ch = input.splice(i, 1)[0];
    usedChars.push(ch);
    if (input.length == 0) {
      permArr.push(usedChars.slice());
    }
    permute(input);
    input.splice(i, 0, ch);
    usedChars.pop();
  }
  return permArr
};


document.write(JSON.stringify(permute([5, 3, 7, 1])));


@SiGanteng। আপনার ফাংশনটি ব্যবহার করার চেষ্টা করে আমার কাছে কিছু অদ্ভুত ঘটনা ঘটছে। আমি এটি একটি জেজে রেখেছি যেখানে আমার সমস্ত "তালিকার ম্যানিপুলেশন ফাংশন" রয়েছে। যদি আমি এটিকে পারমিট ([1,2,3]), এবং পরের পারমিট ([4,5,6]) দিয়ে ব্যবহার করি তবে পরবর্তীকালের আউটপুটটিতে এখনও ফলাফল রয়েছে, প্রথমটি থেকে আউটপুট। কোন ধারণা কিভাবে যে ঠিক কিভাবে ? অনেক ধন্যবাদ !
500


15
আপনার ফাংশনে গ্লোবালগুলি অ্যাক্সেস করা হচ্ছে, খারাপ ফর্ম!
শ্মিদ্দী

123

কিছুটা দেরি হলেও এখানে কিছুটা মার্জিত সংস্করণ যুক্ত করতে চাই। যে কোনও অ্যারে হতে পারে ...

function permutator(inputArr) {
  var results = [];

  function permute(arr, memo) {
    var cur, memo = memo || [];

    for (var i = 0; i < arr.length; i++) {
      cur = arr.splice(i, 1);
      if (arr.length === 0) {
        results.push(memo.concat(cur));
      }
      permute(arr.slice(), memo.concat(cur));
      arr.splice(i, 0, cur[0]);
    }

    return results;
  }

  return permute(inputArr);
}

একটি ES6 (2015) সংস্করণ যুক্ত করা হচ্ছে। মূল ইনপুট অ্যারেটিকেও রূপান্তরিত করে না। ক্রোমে কনসোলে কাজ করে ...

const permutator = (inputArr) => {
  let result = [];

  const permute = (arr, m = []) => {
    if (arr.length === 0) {
      result.push(m)
    } else {
      for (let i = 0; i < arr.length; i++) {
        let curr = arr.slice();
        let next = curr.splice(i, 1);
        permute(curr.slice(), m.concat(next))
     }
   }
 }

 permute(inputArr)

 return result;
}

তাই ...

permutator(['c','a','t']);

উৎপাদনের...

[ [ 'c', 'a', 't' ],
  [ 'c', 't', 'a' ],
  [ 'a', 'c', 't' ],
  [ 'a', 't', 'c' ],
  [ 't', 'c', 'a' ],
  [ 't', 'a', 'c' ] ]

এবং...

permutator([1,2,3]);

উৎপাদনের...

[ [ 1, 2, 3 ],
  [ 1, 3, 2 ],
  [ 2, 1, 3 ],
  [ 2, 3, 1 ],
  [ 3, 1, 2 ],
  [ 3, 2, 1 ] ]

1
আপনি যদি একটি গৌণিক ফাংশনের কুশলী যদি (যেমন মোটামুটি সম্ভবত বিবেচনায় আপনি permutations সাথে ডিল করা হয়), আপনি এটি বাইরের সুযোগ আরম্ভের পরিবর্তন করে গতি বাড়াতে পারে var results = new Array(factorial(inputArr.length)), length=0, তাহলে প্রতিস্থাপন results.push(…)সঙ্গেresults[length++]=…
Cyoce

1
লাইন var cur, memo = memo || [];কি করে?
রাইসাইন্ড

2
@ ব্যবহারকারী 2965967 এটি কার এবং মেমো ঘোষনা করে এবং এটি মেমোটির মান হতে শুরু করে, যদি না এটি মিথ্যা (অপরিজ্ঞাত সহ) হয়, তবে এটি খালি অ্যারে হবে ray অন্য কথায়, এটি একটি ডিফল্ট মান সহ ফাংশন প্যারামিটার সরবরাহ করার চেয়ে কম আদর্শ উপায়।
মিঃ লাভালাম্প

এটি মূল অ্যারেটি পরিবর্তন করে।
শ্মিদ্দী

2
হয় slice()permute(curr.slice(), m.concat(next))সত্যিই প্রয়োজনীয়?
Yoav

82

নিম্নলিখিত খুব কার্যকর অ্যালগরিদম হে (এন!) এ রানটাইম জটিলতায় এন উপাদানগুলির সমস্ত ক্রিয়াকলাপ উত্পন্ন করতে হ্যাপের পদ্ধতি ব্যবহার করে :

function permute(permutation) {
  var length = permutation.length,
      result = [permutation.slice()],
      c = new Array(length).fill(0),
      i = 1, k, p;

  while (i < length) {
    if (c[i] < i) {
      k = i % 2 && c[i];
      p = permutation[i];
      permutation[i] = permutation[k];
      permutation[k] = p;
      ++c[i];
      i = 1;
      result.push(permutation.slice());
    } else {
      c[i] = 0;
      ++i;
    }
  }
  return result;
}

console.log(permute([1, 2, 3]));

একই অ্যালগরিদম ও (এন) এর স্পেস জটিলতায় জেনারেটর হিসাবে প্রয়োগ করা হয়েছিল:

পারফরম্যান্স তুলনা

আপনার প্রয়োগটি নীচের বেঞ্চমার্ক.জেএস টেস্ট স্যুটে যুক্ত করতে নির্দ্বিধায় :

ক্রোম 48-এর জন্য রান-টাইম ফলাফল:


1
একটি নির্দিষ্ট এন = 2 এর ফলাফল সরবরাহ করতে এই কোডটি কীভাবে পরিবর্তন করা যেতে পারে? উদাহরণস্বরূপ, ধরুন আমাদের কাছে তিনটি অক্ষরের একটি সেট রয়েছে: এ, বি এবং সি। আমরা সেটটি থেকে কতগুলি উপায়ে 2 টি চিঠি সাজিয়ে রাখতে পারি তা জিজ্ঞাসা করতে পারি। প্রতিটি সম্ভাব্য বিন্যাস একটি অনুচ্ছেদের উদাহরণ হতে পারে। সম্ভাব্য অনুমতিগুলির সম্পূর্ণ তালিকাটি হ'ল: এবি, এসি, বিএ, বিসি, সিএ এবং সিবি।
a4xrbj1

1
@ a4xrbj1 উদাহরণস্বরূপ এই প্রশ্নের কোড নমুনা দেখুন: স্ট্যাকওভারফ্লো.com/ জিজ্ঞাসা / 7878৮৯২88৮/২ - বা আপনি বিশেষত এই (হিপস) পদ্ধতিটি পরিবর্তন করার বিষয়ে জিজ্ঞাসা করছেন?
le_m

@ লে_ম হ্যাঁ, বিশেষত এটি (গাদা) পদ্ধতিটি এত তাড়াতাড়ি ব্যবহার করে
a4xrbj1

@ a4xrbj1 আমি উপরের লিঙ্কটির অনুরূপ কৌশল ব্যবহার করে স্থির দৈর্ঘ্য n (যেমন AB, AC, BC) এর সমস্ত সংমিশ্রণগুলি গণনা করব (এছাড়াও stackoverflow.com/questions/127704/… দেখুন ) এবং তারপরে প্রতিটি সংমিশ্রণের জন্য হ্যাপের পদ্ধতিটি ব্যবহার করে এর সমস্ত অনুমতিগুলির গণনা করুন। বিশেষত যেমন এন = 2 এর ক্ষেত্রে অবশ্যই অনুকূলিত করা যায়।
le_m

1
জেনারেটর সংস্করণটি সঠিকভাবে কাজ করে না, yield permutation.slice()আপনি কেবল টুকরো টুকরো না করলে কেবল শেষ পুমিটেশন গণনা করা উচিত।
বেলদার

41
var inputArray = [1, 2, 3];

var result = inputArray.reduce(function permute(res, item, key, arr) {
    return res.concat(arr.length > 1 && arr.slice(0, key).concat(arr.slice(key + 1)).reduce(permute, []).map(function(perm) { return [item].concat(perm); }) || item);
}, []);


alert(JSON.stringify(result));

10
বাহ, তীব্রতা এবং ডক্সের অভাব সত্ত্বেও, আমি মনে করি এটি সবচেয়ে মার্জিত উত্তর answer এই অ্যালগরিদম সম্পর্কে আমার ব্যাখ্যাটি হ'ল: অ্যারের প্রতিটি আইটেমের জন্য (হ্রাস), অন্যান্য সমস্ত আইটেম নির্বাচন করুন, সেগুলি (পুনরাবৃত্তভাবে) এবং এই আইটেমটির সাথে একমত রাখুন ute
আরোন

এই সমাধানটি এখানে চেষ্টা করে দেখুন: কোডওয়ার্স.com / kata / reviews / 5254ca2719453dcc0b000280 / groups/… আমি আসল গল্ফ কোডটি একটি পঠনযোগ্যর মধ্যে সরিয়ে ফেলেছি তবে এটি মূলত একই same এটির সাথে সমস্যাটি হ'ল এটি সদৃশ তৈরি করে এবং ফলাফলটিতে আমাকে আরও একটি কাজ .filter(uniq)করতে হয়েছিল।
আন্দ্রে মিখায়লোভ - লোলমাস

1
ধারণার সমান্তরাল একটি লিস্প আছে [1,2,3].length == 3 && "foo" || "bar"বা [1,2].length == 3 && "foo" || "bar"ওহ আমার! এখানে! (or (and (= 3 2) (print "hello!")) (print "goodbye"))
দিমিত্রি

@ লোলমাস-আন্দ্রে মিখায়লোভ কীভাবে সদৃশতা সরিয়ে ফেলবেন দয়া করে উত্তরটি আপডেট করুন দয়া করে
পারদীপ জৈন

@ পারদীপজাইন আমি উপরের আমার সমাধানের জন্য একটি লিঙ্ক দিয়েছি।
আন্দ্রে মিখায়লোভ - লোলমাস

21

আমি সিগ্যান্টেং এর উত্তর উন্নত করেছি

এখন permuteএকাধিকবার কল করা সম্ভব , কারণ permArrএবং usedCharsপ্রতিবার সাফ হয়ে গেছে।

function permute(input) {
    var permArr = [],
        usedChars = [];
    return (function main() {
        for (var i = 0; i < input.length; i++) {
            var ch = input.splice(i, 1)[0];
            usedChars.push(ch);
            if (input.length == 0) {
                permArr.push(usedChars.slice());
            }
            main();
            input.splice(i, 0, ch);
            usedChars.pop();
        }
        return permArr;
    })();
}


10

নিম্নলিখিত ফাংশনটি যে কোনও ধরণের অ্যারেকে অনুমতি দেয় এবং পাওয়া প্রতিটি ক্রিয়াকলাপে একটি নির্দিষ্ট কলব্যাক ফাংশন কল করে:

/*
  Permutate the elements in the specified array by swapping them
  in-place and calling the specified callback function on the array
  for each permutation.

  Return the number of permutations.

  If array is undefined, null or empty, return 0.

  NOTE: when permutation succeeds, the array should be in the original state
  on exit!
*/
  function permutate(array, callback) {
    // Do the actual permuation work on array[], starting at index
    function p(array, index, callback) {
      // Swap elements i1 and i2 in array a[]
      function swap(a, i1, i2) {
        var t = a[i1];
        a[i1] = a[i2];
        a[i2] = t;
      }

      if (index == array.length - 1) {
        callback(array);
        return 1;
      } else {
        var count = p(array, index + 1, callback);
        for (var i = index + 1; i < array.length; i++) {
          swap(array, i, index);
          count += p(array, index + 1, callback);
          swap(array, i, index);
        }
        return count;
      }
    }

    if (!array || array.length == 0) {
      return 0;
    }
    return p(array, 0, callback);
  }

আপনি যদি এটিকে কল করেন:

  // Empty array to hold results
  var result = [];
  // Permutate [1, 2, 3], pushing every permutation onto result[]
  permutate([1, 2, 3], function (a) {
    // Create a copy of a[] and add that to result[]
    result.push(a.slice(0));
  });
  // Show result[]
  document.write(result);

আমি মনে করি এটি আপনার যা প্রয়োজন ঠিক তা করবে - অ্যারের resultঅনুমতিগুলি [1, 2, 3] এর সাথে পরিচিত একটি অ্যারে পূরণ করুন । ফলাফল হলো:

[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,2,1],[3,1,2]]

জেএসফিডেলে কিছুটা পরিষ্কার কোড: http://jsfiddle.net/MgmMg/6/


10

এই প্রশ্নের বেশিরভাগ উত্তরগুলি ব্যয়বহুল ক্রিয়াকলাপগুলিতে ব্যবহার করে যেমন অ্যারেতে ধারাবাহিক সন্নিবেশ এবং আইটেমগুলি মোছা, বা পুনরাবৃত্তিতে অ্যারেগুলি অনুলিপি করা।

পরিবর্তে, এটি সাধারণ ব্যাকট্র্যাকিং সমাধান:

function permute(arr) {
  var results = [],
      l = arr.length,
      used = Array(l), // Array of bools. Keeps track of used items
      data = Array(l); // Stores items of the current permutation
  (function backtracking(pos) {
    if(pos == l) return results.push(data.slice());
    for(var i=0; i<l; ++i) if(!used[i]) { // Iterate unused items
      used[i] = true;      // Mark item as used
      data[pos] = arr[i];  // Assign item at the current position
      backtracking(pos+1); // Recursive call
      used[i] = false;     // Mark item as not used
    }
  })(0);
  return results;
}
permute([1,2,3,4]); // [  [1,2,3,4], [1,2,4,3], /* ... , */ [4,3,2,1]  ]

যেহেতু ফলাফল অ্যারে বিশাল হবে, তাই একই সাথে সমস্ত ডেটা বরাদ্দ না করে একের পর এক ফলাফল পুনরাবৃত্তি করা ভাল ধারণা হতে পারে। ES6 এ, জেনারেটরগুলির সাথে এটি করা যেতে পারে:

function permute(arr) {
  var l = arr.length,
      used = Array(l),
      data = Array(l);
  return function* backtracking(pos) {
    if(pos == l) yield data.slice();
    else for(var i=0; i<l; ++i) if(!used[i]) {
      used[i] = true;
      data[pos] = arr[i];
      yield* backtracking(pos+1);
      used[i] = false;
    }
  }(0);
}
var p = permute([1,2,3,4]);
p.next(); // {value: [1,2,3,4], done: false}
p.next(); // {value: [1,2,4,3], done: false}
// ...
p.next(); // {value: [4,3,2,1], done: false}
p.next(); // {value: undefined, done: true}

6

এটি একটি আকর্ষণীয় কাজ এবং এখানে আমার অবদান রয়েছে। এটি খুব সহজ এবং দ্রুত। আগ্রহী হলে আমার সাথে সহ্য করুন এবং পড়ুন।

আপনি যদি এই কাজটি দ্রুত করতে চান তবে আপনাকে অবশ্যই ডায়নামিকাল প্রোগ্রামিংয়ে নিজেকে নিয়ে যেতে হবে। যার অর্থ আপনার পুনরাবৃত্তির পদ্ধতির কথা ভুলে যাওয়া উচিত। এটা সত্যি...

হিপ এর পদ্ধতি ব্যবহার করে ওকে লে_এম এর কোড এখন পর্যন্ত সবচেয়ে দ্রুত বলে মনে হচ্ছে। আমি আমার অ্যালগরিদমের কোনও নাম পাইনি, আমি জানি না এটি ইতিমধ্যে বাস্তবায়ন হয়েছে কি না তবে এটি খুব সহজ এবং দ্রুত। সমস্ত গতিশীল প্রোগ্রামিং পদ্ধতির সাথে আমরা সহজ সমস্যাটি দিয়ে শুরু করব এবং চূড়ান্ত ফলাফলের জন্য যাব।

ধরে নিচ্ছি যে আমাদের একটি অ্যারে রয়েছে যা a = [1,2,3]দিয়ে শুরু করব

r = [[1]]; // result
t = [];    // interim result

তারপরে এই তিনটি পদক্ষেপ অনুসরণ করুন;

  1. আমাদের r(ফলাফল) অ্যারের প্রতিটি আইটেমের জন্য আমরা ইনপুট অ্যারের পরবর্তী আইটেমটি যুক্ত করব।
  2. আমরা প্রতিটি আইটেমটির দৈর্ঘ্য বহুবার ঘুরিয়ে দেব এবং প্রতিটি উদাহরণ অন্তর্বর্তী ফলাফল অ্যারেতে সংরক্ষণ করব t। (প্রথমটি ব্যতীত 0 টি আবর্তনের সাথে সময় নষ্ট না করা ব্যতীত)
  3. একবার rঅন্তর্বর্তী অ্যারের সমস্ত আইটেম সমাপ্ত করার পরে tফলাফলের পরবর্তী স্তরটি ধরে রাখা উচিত যাতে আমরা r = t; t = [];ইনপুট অ্যারের দৈর্ঘ্য না হওয়া পর্যন্ত চালিয়ে যাই এবং চালিয়ে যেতে পারি a

সুতরাং নীচে আমাদের পদক্ষেপ;

r array   | push next item to |  get length many rotations
          |  each sub array   |       of each subarray
-----------------------------------------------------------
[[1]]     |     [[1,2]]       |     [[1,2],[2,1]]
----------|-------------------|----------------------------
[[1,2],   |     [[1,2,3],     |     [[1,2,3],[2,3,1],[3,1,2],
 [2,1]]   |      [2,1,3]]     |      [2,1,3],[1,3,2],[3,2,1]]
----------|-------------------|----------------------------
previous t|                   |
-----------------------------------------------------------

সুতরাং এখানে কোড

function perm(a){
  var r = [[a[0]]],
      t = [],
      s = [];
  if (a.length <= 1) return a;
  for (var i = 1, la = a.length; i < la; i++){
    for (var j = 0, lr = r.length; j < lr; j++){
      r[j].push(a[i]);
      t.push(r[j]);
      for(var k = 1, lrj = r[j].length; k < lrj; k++){
        for (var l = 0; l < lrj; l++) s[l] = r[j][(k+l)%lrj];
        t[t.length] = s;
        s = [];
      }
    }
    r = t;
    t = [];
  }
  return r;
}

var arr = [0,1,2,4,5];
console.log("The length of the permutation is:",perm(arr).length);
console.time("Permutation test");
for (var z = 0; z < 2000; z++) perm(arr);
console.timeEnd("Permutation test");

একাধিক পরীক্ষায় আমি এটি দেখেছি যে এটি [0,1,2,3,4] এর 120 ক্রমটি 25 ~ 35ms তে 2000 বারের জন্য সমাধান করছে।


1
এটি বিভিন্ন দৈর্ঘ্যের / ওয়ার্ম-আপ পুনরুক্তি ইত্যাদির জন্য এফএফ / উবুন্টুতে হিপ পদ্ধতির চেয়ে ধীরে ধীরে ধীরে ধীরে দ্রুতগতিতে চলেছে বলে মনে হয়, বিভিন্ন ইঞ্জিনের ফলাফল দেখতে কোনও জাসপাফের প্রয়োজন হবে need
le_m

1
@ লে_ম ঠিক আছে আমি উবুন্টু এবং এএমডি সিপিইউতে @ জেএসবেইন কিছু পরীক্ষা করেছি : ক্রোমের সাথে rotatePerm( উপরেরটি ) নিয়মিত 1.2 গতিযুক্ত । এফএফের সাথে কোনও ধারাবাহিকতা নেই। একাধিক পরীক্ষার পরে কখনও কখনও heapPerm2 বার দ্রুত হয় কিছু সময় rotatePerm1.1 গুণ দ্রুত হয়। অপেরা বা এপিফ্যানির মতো অন্যান্য ওয়েব-কিট ব্রাউজারগুলির সাথে rotatePermধারাবাহিকভাবে 1.1 গুণ দ্রুত গতিতে দেখা যায়। তবে এজ সহ heapPermপ্রতি একক সময় নিয়মিত 1.2 গুণ দ্রুত হয়।
Redu

1
নিস! এটি দেখে মনে হয় - কমপক্ষে এফএফ / উবুন্টুতে - হিপ পদ্ধতির পারফরম্যান্স মূলত অ্যারে অনুলিপি করার কার্য সম্পাদনের উপর নির্ভর করে। স্লাইসিং বনাম পুশিংয়ের তুলনা করার জন্য আমি আপনার মানদণ্ডটি সংশোধন করেছি: jsben.ch/#/x7mYh - এফএফ এবং ছোট ইনপুট অ্যারেগুলির জন্য, পুশিং আরও দ্রুত বলে মনে হচ্ছে
le_m

2
দুর্দান্ত হবে যদি গাদা পদ্ধতিটি পারফরম্যান্সের ভিত্তিতে মারধর করা যায়। উপায় দ্বারা, আপনার পদ্ধতি একই 1977 কাগজ আমি গাদা এর পদ্ধতির জন্য একটি রেফারেন্স হিসেবে ব্যবহার করা থেকে ল্যাংডন এর এলগরিদম (পৃষ্ঠা 16) একই আউটপুট উত্পন্ন: homepage.math.uiowa.edu/~goodman/22m150.dir/2007/...
le_m

2
@le_m আমি সবেমাত্র যাচাই করেছি এবং এটি একই জিনিস বলে মনে হচ্ছে। তিনি যেমন প্রয়োগ করেছিলেন তেমন ঘোরানোও আমার মনে হচ্ছে। মাত্র 40 বছরের বিলম্বের সাথে। যেহেতু আমি আমার উত্তরে উল্লেখ করেছি এটি আসলে খুব সহজ পদ্ধতি। দ্রুত ঘূর্ণন উপলভ্য হলেই পছন্দ হিসাবে উল্লেখ করা হয়। বর্তমানে আমি হাস্কেলের সাথে আছি এবং তালিকা তৈরি করার পদ্ধতিটি একটি অন্তর্নিহিত রয়েছে (চলুন অ্যারে বলতে দিন) চিরকালীন জন্য (অলস মূল্যায়ন একটি অসীম পুনরাবৃত্তিকে কোনও সমস্যা দেয় না) এবং এটি কার্যকর হতে পারে। তবুও, হাস্কেলের ইতিমধ্যে একটি স্ট্যান্ডার্ড permutationsফাংশন রয়েছে :)
রেডু

6

হাস্কেল থেকে অনুপ্রাণিত কিছু সংস্করণ:

perms [] = [[]]
perms xs = [ x:ps | x <- xs , ps <- perms ( xs\\[x] ) ]

function perms(xs) {
  if (!xs.length) return [[]];
  return xs.flatMap((xi, i) => {
    // get permutations of xs without its i-th item, then prepend xi to each
    return perms([...xs.slice(0,i), ...xs.slice(i+1)]).map(xsi => [xi, ...xsi]);
  });
}
document.write(JSON.stringify(perms([1,2,3])));


5

বাহ্যিক অ্যারে বা অতিরিক্ত ফাংশনের প্রয়োজন ছাড়াই উত্তর দিন

function permutator (arr) {
  var permutations = [];
  if (arr.length === 1) {
    return [ arr ];
  }

  for (var i = 0; i <  arr.length; i++) { 
    var subPerms = permutator(arr.slice(0, i).concat(arr.slice(i + 1)));
    for (var j = 0; j < subPerms.length; j++) {
      subPerms[j].unshift(arr[i]);
      permutations.push(subPerms[j]);
    }
  }
  return permutations;
}

আপনি কি এটি থেকে একটি সমন্বয় করতে পারেন? stackoverflow.com/questions/53555563/...
Techdive

5

আজকাল (2020) সবচেয়ে দ্রুততম, সর্বাধিক (রিসোর্সগুলি) কার্যকর এবং সর্বাধিক মার্জিত সংস্করণ

function getArrayMutations(arr, perms = [], len = arr.length) {
  if (len === 1) perms.push(arr.slice(0))

  for (let i = 0; i < len; i++) {
    getArrayMutations(arr, perms, len - 1)

    len % 2 // parity dependent adjacent elements swap
      ? [arr[0], arr[len - 1]] = [arr[len - 1], arr[0]]
      : [arr[i], arr[len - 1]] = [arr[len - 1], arr[i]]
  }

  return perms
}

const arrayToMutate = [1, 2, 3, 4, 5, 6, 7, 8, 9]

const startTime = performance.now()
const arrayOfMutations = getArrayMutations(arrayToMutate)
const stopTime = performance.now()
const duration = (stopTime - startTime) / 1000

console.log(`${arrayOfMutations.length.toLocaleString('en-US')} permutations found in ${duration.toLocaleString('en-US')}s`)


হাই, আপনি কী বোঝাতে চাইছেন len % 2 // parity dependent adjacent elements swapএবং এর অর্থ কী ?
প্রমেশ বাজরাচার্য

আমার কোডটি অ্যারের অনুমতিগুলি উত্পন্ন করতে "হিপস অ্যালগরিদম" ব্যবহার করে। সুতরাং, আপনি যদি জানতে চান যে আমার কোডটি হুডের নীচে কীভাবে কাজ করে তবে হ্যাপের অ্যালগরিদমের এই ব্যাখ্যাটি পড়ুন: en.m.wikedia.org/wiki/Heap%27s_algorithm
ভ্লাদিস্লাভ লাডিকি

আপনি কি ফলাফল মুদ্রণের চেষ্টা করেছেন? সর্বোচ্চ 10 টির উপরে অ্যারে উপাদানগুলি কীভাবে নিয়ন্ত্রণ করবেন?
মার্ভিক্স

4

এখানে একটি দুর্দান্ত সমাধান

const rotations = ([l, ...ls], right=[]) =>
  l ? [[l, ...ls, ...right], ...rotations(ls, [...right, l])] : []

const permutations = ([x, ...xs]) =>
  x ? permutations(xs).flatMap((p) => rotations([x, ...p])) : [[]]
  
console.log(permutations("cat"))


2

এখানে আরও একটি "পুনরাবৃত্ত" সমাধান রয়েছে।

function perms(input) {
  var data = input.slice();
  var permutations = [];
  var n = data.length;

  if (n === 0) {
    return [
      []
    ];
  } else {
    var first = data.shift();
    var words = perms(data);
    words.forEach(function(word) {
      for (var i = 0; i < n; ++i) {
        var tmp = word.slice();
        tmp.splice(i, 0, first)
        permutations.push(tmp);
      }
    });
  }

  return permutations;
}

var str = 'ABC';
var chars = str.split('');
var result = perms(chars).map(function(p) {
  return p.join('');
});

console.log(result);

আউটপুট:

[ 'ABC', 'BAC', 'BCA', 'ACB', 'CAB', 'CBA' ]

আপনি কি এর জন্য একটি সংমিশ্রণ তৈরি করতে পারেন? stackoverflow.com/questions/53555563/...
Techdive

2
   function perm(xs) {
       return xs.length === 0 ? [[]] : perm(xs.slice(1)).reduce(function (acc, ys) {
        for (var i = 0; i < xs.length; i++) {
          acc.push([].concat(ys.slice(0, i), xs[0], ys.slice(i)));
        }
        return acc;
      }, []);
    }

এটি দিয়ে পরীক্ষা করুন:

console.log(JSON.stringify(perm([1, 2, 3,4])));

2

অন্যান্য উত্তরগুলির বেশিরভাগই নতুন জাভাস্ক্রিপ্ট জেনারেটর ফাংশন ব্যবহার করে না যা এই ধরণের সমস্যার নিখুঁত সমাধান। আপনার সম্ভবত মেমরির সময় কেবলমাত্র একটির অনুমতি প্রয়োজন। এছাড়াও, আমি বিভিন্ন সূচকের ক্রম উৎপন্ন করতে পছন্দ করি কারণ এটি আমাকে প্রতিটি অনুক্রমের সূচী করতে এবং সরাসরি কোনও নির্দিষ্ট অনুক্রমের দিকে ঝাঁপিয়ে পড়ার পাশাপাশি অন্য কোনও সংগ্রহকে নিষ্ক্রিয় করতে ব্যবহার করতে পারে।

// ES6 generator version of python itertools [permutations and combinations]
const range = function*(l) { for (let i = 0; i < l; i+=1) yield i; }
const isEmpty = arr => arr.length === 0;

const permutations = function*(a) {
    const r = arguments[1] || [];
    if (isEmpty(a)) yield r;
    for (let i of range(a.length)) {
        const aa = [...a];
        const rr = [...r, ...aa.splice(i, 1)];
        yield* permutations(aa, rr);
    }
}
console.log('permutations of ABC');
console.log(JSON.stringify([...permutations([...'ABC'])]));

const combinations = function*(a, count) {
    const r = arguments[2] || [];
    if (count) {
        count = count - 1;
        for (let i of range(a.length - count)) {
            const aa = a.slice(i);
            const rr = [...r, ...aa.splice(0, 1)];
            yield* combinations(aa, count, rr);
        }
    } else {
        yield r;
    }
}
console.log('combinations of 2 of ABC');
console.log(JSON.stringify([...combinations([...'ABC'], 2)]));



const permutator = function() {
    const range = function*(args) {
        let {begin = 0, count} = args;
        for (let i = begin; count; count--, i+=1) {
            yield i;
        }
    }
    const factorial = fact => fact ? fact * factorial(fact - 1) : 1;

    return {
        perm: function(n, permutationId) {
            const indexCount = factorial(n);
            permutationId = ((permutationId%indexCount)+indexCount)%indexCount;

            let permutation = [0];
            for (const choiceCount of range({begin: 2, count: n-1})) {
                const choice = permutationId % choiceCount;
                const lastIndex = permutation.length;

                permutation.push(choice);
                permutation = permutation.map((cv, i, orig) => 
                    (cv < choice || i == lastIndex) ? cv : cv + 1
                );

                permutationId = Math.floor(permutationId / choiceCount);
            }
            return permutation.reverse();
        },
        perms: function*(n) {
            for (let i of range({count: factorial(n)})) {
                yield this.perm(n, i);
            }
        }
    };
}();

console.log('indexing type permutator');
let i = 0;
for (let elem of permutator.perms(3)) {
  console.log(`${i}: ${elem}`);
  i+=1;
}
console.log();
console.log(`3: ${permutator.perm(3,3)}`);


2
#!/usr/bin/env node
"use strict";

function perm(arr) {
    if(arr.length<2) return [arr];
    var res = [];
    arr.forEach(function(x, i) {
        perm(arr.slice(0,i).concat(arr.slice(i+1))).forEach(function(a) {
            res.push([x].concat(a));
        });
    });
    return res;
}

console.log(perm([1,2,3,4]));

2

এখানে আমি তৈরি করেছি ...

const permute = (ar) =>
  ar.length === 1 ? ar : ar.reduce( (ac,_,i) =>
    {permute([...ar.slice(0,i),...ar.slice(i+1)]).map(v=>ac.push([].concat(ar[i],v))); return ac;},[]);

এবং এখানে এটি আবার তবে কম গাers়ভাবে লেখা! ...

function permute(inputArray) {
  if (inputArray.length === 1) return inputArray;
  return inputArray.reduce( function(accumulator,_,index){
    permute([...inputArray.slice(0,index),...inputArray.slice(index+1)])
      .map(value=>accumulator.push([].concat(inputArray[index],value)));
    return accumulator;
  },[]);
}

এটি কীভাবে কাজ করে: অ্যারে যদি এক উপাদানের চেয়ে দীর্ঘ হয় তবে এটি প্রতিটি উপাদানের মধ্য দিয়ে পদক্ষেপ নেয় এবং যুক্তি হিসাবে এটি বাকী উপাদানগুলির সাথে নিজেকে পুনরাবৃত্ত কল দিয়ে যুক্ত করে তোলে। এটি মূল অ্যারেটি পরিবর্তন করে না।


2

ফ্ল্যাটম্যাপ ব্যবহার করে কার্যকরী উত্তর:

const getPermutationsFor = (arr, permutation = []) =>
  arr.length === 0
    ? [permutation]
    : arr.flatMap((item, i, arr) =>
        getPermutationsFor(
          arr.filter((_,j) => j !== i),
          [...permutation, item]
        )
      );

1

"use strict";
function getPermutations(arrP) {
    var results = [];
    var arr = arrP;
    arr.unshift(null);
    var length = arr.length;

    while (arr[0] === null) {

        results.push(arr.slice(1).join(''));

        let less = null;
        let lessIndex = null;

        for (let i = length - 1; i > 0; i--) {
            if(arr[i - 1] < arr[i]){
                less = arr[i - 1];
                lessIndex = i - 1;
                break;
            }
        }

        for (let i = length - 1; i > lessIndex; i--) {
            if(arr[i] > less){
                arr[lessIndex] = arr[i];
                arr[i] = less;
                break;
            }
        }

        for(let i = lessIndex + 1; i<length; i++){
           for(let j = i + 1; j < length; j++){
               if(arr[i] > arr[j] ){
                   arr[i] = arr[i] + arr[j];
                   arr[j] = arr[i] - arr[j];
                   arr[i] = arr[i] - arr[j];
               }
           }
        }
    }

    return results;
}

var res = getPermutations([1,2,3,4,5]);
var out = document.getElementById('myTxtArr');
res.forEach(function(i){ out.value+=i+', '});
textarea{
   height:500px;
  width:500px;
}
<textarea id='myTxtArr'></textarea>

আউটপুটগুলি ডিক্সিকোগ্রাফিকভাবে ক্রমানুসারে আদেশ করা হয়েছে। শুধুমাত্র সংখ্যা নিয়ে কাজ করে। অন্য ক্ষেত্রে, আপনাকে 34 নম্বর লাইনে অদলবদল পরিবর্তন করতে হবে।


1

@ সিআরএল দ্বারা হাস্কেল-স্টাইলের সমাধানের সাথে একইভাবে, তবে এর সাথে কাজ করছেন reduce:

function permutations( base ) {
  if (base.length == 0) return [[]]
  return permutations( base.slice(1) ).reduce( function(acc,perm) {
    return acc.concat( base.map( function(e,pos) {
      var new_perm = perm.slice()
      new_perm.splice(pos,0,base[0])
      return new_perm
    }))
  },[])    
}

1

মানচিত্র / হ্রাসের জন্য এটি খুব সুন্দর ব্যবহারের কেস:

function permutations(arr) {
    return (arr.length === 1) ? arr :
    arr.reduce((acc, cv, index) => {
        let remaining = [...arr];
        remaining.splice(index, 1);
        return acc.concat(permutations(remaining).map(a => [].concat(cv,a)));
    }, []);
}
  • প্রথমত, আমরা বেস কেসটি পরিচালনা করি এবং কেবলমাত্র অ্যারেটিতে কেবল আইটেম থাকলে তা ফিরিয়ে আনি
  • অন্য সব ক্ষেত্রে
    • আমরা একটি ফাঁকা অ্যারে তৈরি করি
    • ইনপুট-অ্যারে উপর লুপ
    • এবং বর্তমান মানের একটি অ্যারে এবং বাকি অ্যারের সমস্ত ক্রম যুক্ত করুন [].concat(cv,a)

1

এখানে একটি ন্যূনতম ES6 সংস্করণ। সমতল এবং ফাংশন ছাড়াই লোডাশ থেকে টানা যায়।

const flatten = xs =>
    xs.reduce((cum, next) => [...cum, ...next], []);

const without = (xs, x) =>
    xs.filter(y => y !== x);

const permutations = xs =>
    flatten(xs.map(x =>
        xs.length < 2
            ? [xs]
            : permutations(without(xs, x)).map(perm => [x, ...perm])
    ));

ফলাফল:

permutations([1,2,3])
// [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

1
perm = x => x[0] ?  x.reduce((a, n) => (perm(x.filter(m => m!=n)).forEach(y => a.push([n,...y])), a), []): [[]]

2
আপনি একটি ব্যাখ্যা যোগ করতে পারেন দয়া করে।
মেহেদী বাউনিয়া

3
যদিও এই উত্তরটি প্রশ্নের সমাধান করতে পারে, এটি কীভাবে বা কেন এটি করে তার কোনও ব্যাখ্যা নেই।
21

1

const permutations = array => {
  let permut = [];
  helperFunction(0, array, permut);
  return permut;
};

const helperFunction = (i, array, permut) => {
  if (i === array.length - 1) {
    permut.push(array.slice());
  } else {
    for (let j = i; j < array.length; j++) {
      swapElements(i, j, array);
      helperFunction(i + 1, array, permut);
      swapElements(i, j, array);
    }
  }
};

function swapElements(a, b, array) {
  let temp = array[a];
  array[a] = array[b];
  array[b] = temp;
}

console.log(permutations([1, 2, 3]));


1

বেশ দেরী. এখনও যদি সেক্ষেত্রে এটি কাউকে সহায়তা করে।

function permute(arr) {
  if (arr.length == 1) return arr

  let res = arr.map((d, i) => permute([...arr.slice(0, i),...arr.slice(i + 1)])
                              .map(v => [d,v].join(''))).flat()

  return res
}

console.log(permute([1,2,3,4]))


1

আমার এটির একটি সংস্করণ তৈরি করার সময় ক্র্যাক হয়েছিল যা সংক্ষিপ্তভাবে এখনও পঠনযোগ্য এবং খাঁটি কার্যকরী প্রোগ্রামিং হওয়ার চেষ্টা করে।

function stringPermutations ([...input]) {
  if (input.length === 1) return input;

  return input
    .map((thisChar, index) => {
      const remainingChars = [...input.slice(0, index), ...input.slice(index + 1)];
      return stringPermutations(remainingChars)
        .map(remainder => thisChar + remainder);
    })
    .reduce((acc, cur) => [...acc, ...cur]);
}

নোট করুন যে আর্গুমেন্ট ফর্ম্যাটিং একটি ইনপুট স্ট্রিংকে একটি অ্যারেতে পরিণত করে। নিশ্চিত না যে এটি কিছুটা যাদুকর কিনা .. নিশ্চিত নই যে আমি এটি বুনোতে দেখেছি। সত্য পঠনযোগ্যতার জন্য আমি সম্ভবত input = [...input]ফাংশনের প্রথম লাইনের জন্য করতাম ।


1

এটি হিপের আলগোরিদিম (@ লে_ম এর অনুরূপ) এর পুনরাবৃত্তি ব্যতীত একটি বাস্তবায়ন।

function permute_kingzee(arr,n=arr.length,out=[]) {
    if(n == 1) {
        return out.push(arr.slice());
    } else {
        for(let i=0; i<n; i++) {
            permute_kingzee(arr,n-1, out);
            let j = ( n % 2 == 0 ) ? i : 0;
            let t = arr[n-1];
            arr[n-1] = arr[j];
            arr[j] = t;
        }
        return out;
    }
}

দেখে মনে হচ্ছে এটি বেশ দ্রুত: https://jsfiddle.net/3brqzaLe/


1

সাইটে আমার প্রথম অবদান। এছাড়াও, আমি যে পরীক্ষাগুলি করেছি তার অনুসারে, এই কোডটি এখানে এই তারিখের আগে এখানে উল্লিখিত অন্যান্য সমস্ত পদ্ধতির তুলনায় দ্রুত চলে, অবশ্যই কয়েকটি মান রয়েছে তবে এটি খুব কম, তবে খুব বেশি সংযোজন করার সময় সময় তাত্পর্যপূর্ণভাবে বৃদ্ধি পায়।

function permutations(arr) {
    var finalArr = [];
    function iterator(arrayTaken, tree) {
        var temp;
        for (var i = 0; i < tree; i++) {
            temp = arrayTaken.slice();
            temp.splice(tree - 1 - i, 0, temp.splice(tree - 1, 1)[0]);
            if (tree >= arr.length) {
                finalArr.push(temp);
            } else {
                iterator(temp, tree + 1);
            }
        }
    }
    iterator(arr, 1);
    return finalArr;
};

আমি একটি পারফরম্যান্স তুলনা stackoverflow.com/a/37580979/1647737 যুক্ত করেছি - আপডেট করতে নির্দ্বিধায়।
le_m

0

আমি জাভাস্ক্রিপ্টে কোনও অ্যারেকে কীভাবে অনুমতি দিতে পারি তা প্রদর্শনের জন্য একটি পোস্ট লিখেছিলাম । এখানে কোড যা এটি করে।

var count=0;
function permute(pre,cur){ 
    var len=cur.length;
    for(var i=0;i<len;i++){
        var p=clone(pre);
        var c=clone(cur);
        p.push(cur[i]);
        remove(c,cur[i]);
        if(len>1){
            permute(p,c);
        }else{
            print(p);
            count++;
        }
    }
}
function print(arr){
    var len=arr.length;
    for(var i=0;i<len;i++){
        document.write(arr[i]+" ");
    }
    document.write("<br />");
}
function remove(arr,item){
    if(contains(arr,item)){
        var len=arr.length;
        for(var i = len-1; i >= 0; i--){ // STEP 1
            if(arr[i] == item){             // STEP 2
                arr.splice(i,1);              // STEP 3
            }
        }
    }
}
function contains(arr,value){
    for(var i=0;i<arr.length;i++){
        if(arr[i]==value){
            return true;
        }
    }
    return false;
}
function clone(arr){
    var a=new Array();
    var len=arr.length;
    for(var i=0;i<len;i++){
        a.push(arr[i]);
    }
    return a;
}

শুধু কল

পারমিট ([]], [1,2,3,4])

কাজ করবে. এটি কীভাবে কাজ করে তার বিশদগুলির জন্য, দয়া করে সেই পোস্টের ব্যাখ্যাটি দেখুন।


0
function nPr(xs, r) {
    if (!r) return [];
    return xs.reduce(function(memo, cur, i) {
        var others  = xs.slice(0,i).concat(xs.slice(i+1)),
            perms   = nPr(others, r-1),
            newElms = !perms.length ? [[cur]] :
                      perms.map(function(perm) { return [cur].concat(perm) });
        return memo.concat(newElms);
    }, []);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.