Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2017
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.86 KB | None | 0 0
  1. function factorial(num) {
  2. var fact = 1;
  3. for(var i=2; i<=num; i++) {
  4. fact *= i;
  5. }
  6. return fact;
  7. }
  8.  
  9. function getReps(str) {
  10. var sortedLetters = str.split("").sort();
  11. var reps = [];
  12. var currentLetter, numberOfLetters;
  13.  
  14. if(str.length >= 1) {
  15. currentLetter = sortedLetters[0];
  16. numberOfLetters = 1;
  17. }
  18. for(var i = 1; i < sortedLetters.length; i++) {
  19. if(sortedLetters[i] === currentLetter) {
  20. numberOfLetters++;
  21. } else {
  22. if (numberOfLetters > 1) {
  23. reps.push(numberOfLetters);
  24. }
  25. currentLetter = sortedLetters[i];
  26. numberOfLetters = 1;
  27. }
  28. }
  29. if(numberOfLetters > 1) {
  30. reps.push(numberOfLetters);
  31. }
  32. return reps;
  33. }
  34.  
  35. function mul(str,num) {
  36. var result = '';
  37. for(var i=0; i<num; i++) {
  38. result += str;
  39. }
  40. return result;
  41. }
  42.  
  43. function binomial(n, chooseK) {
  44. var common = factorial(n - chooseK)*factorial(chooseK);
  45. return Math.round(factorial(n)/common);
  46. }
  47.  
  48. function tryMoveNthA(nth, str) {
  49. for(var i = str.length-1; i>=0; i--) {
  50. if(str[i] === 'a') {
  51. nth--;
  52. }
  53. if(nth < 0) {
  54. if ((i < str.length-1)&&(str[i+1]!=='a')) {
  55. return str.substring(0, i) + 'xa' + str.substring(i+2);
  56. } else {
  57. return null;
  58. }
  59. }
  60. }
  61.  
  62. return null;
  63. }
  64.  
  65. function glueAfrom(nth, str) {
  66. var aFound = 0;
  67.  
  68. for(var i = str.length-1; i>=0; i--) {
  69. if(str[i] === 'a') {
  70. aFound++;
  71. }
  72. if(aFound === nth+1) {
  73. // aaxxaaxxxaxa
  74. // aaxxaaaaxxxx
  75. var xAtEnd = str.length - i - (nth+1);
  76. return str.substring(0,i)+mul('a', nth + 1)+mul('x', xAtEnd);
  77. }
  78. }
  79.  
  80. return null;
  81. }
  82.  
  83. function Form(aNumber, xNumber,separators) {
  84. this.form = '';
  85. this.separators = separators;
  86. this.aNumber = aNumber;
  87. this.xNumber = xNumber;
  88.  
  89. this.firstPossibleGoodForm = function () {
  90. var aNumber = this.aNumber;
  91. var xNumber = this.xNumber;
  92. this.form = '';
  93.  
  94. while(aNumber > 0) {
  95. this.form += 'a';
  96. if(this.isCorrect()) {
  97. aNumber--;
  98. } else {
  99. if(xNumber > 0) {
  100. var str = this.form;
  101. str = str.substring(0, str.length-1) + 'x';
  102. this.form = str;
  103. xNumber--;
  104. } else {
  105. return false;
  106. }
  107. }
  108. }
  109. for(var j=0; j<xNumber; j++) {
  110. this.form += 'x';
  111. }
  112. return true;
  113. };
  114.  
  115. this.nextForm = function () {
  116. /*
  117. aaaxaaxax
  118. aaaxaaxxa
  119. aaaxaxaax
  120. aaaxaxaxa
  121. aaaxaxxaa
  122. aaaxxaaax
  123. aaaxaaaxa
  124. */
  125. var nextForm = new Form(this.aNumber, this.xNumber, this.separators);
  126. var str = this.form;
  127. for (var i = 0; i<this.aNumber; i++) {
  128. var newStr = tryMoveNthA(i, str);
  129. if(newStr !== null) {
  130. newStr = glueAfrom(i, newStr);
  131. nextForm.form = newStr;
  132. return nextForm;
  133. }
  134. }
  135.  
  136. return null;
  137. };
  138.  
  139. this.nextPossibleGoodForm = function () {
  140.  
  141. var nextForm = this.nextForm();
  142. while((nextForm !== null)&&(!nextForm.isCorrect())) {
  143. nextForm = nextForm.nextForm();
  144. }
  145. return nextForm;
  146. };
  147.  
  148. this.subFormsSeparators = function () {
  149. separators = {};
  150. var reduc = 0;
  151. for(var i=0; i<this.form.length; i++) {
  152. if((this.form[i] === 'a') || (this.separators.hasOwnProperty(i))){
  153. separators[i-reduc] = true;
  154. }
  155. if(this.form[i]==='a') {
  156. reduc++;
  157. }
  158. }
  159.  
  160. return separators;
  161. };
  162.  
  163. this.isPerfect = function () {
  164. var str = this.toStr();
  165. return str.match(/xx/) === null;
  166. };
  167.  
  168. this.isCorrect = function () {
  169. var prev = 'x';
  170. for (var i=0; i<this.form.length; i++) {
  171. var separatorBefore = this.separators.hasOwnProperty(i);
  172. if((prev === 'a')&&(this.form[i] === 'a')&&(!separatorBefore)) {
  173. return false;
  174. }
  175. prev = this.form[i];
  176. }
  177.  
  178. return true;
  179. };
  180.  
  181. this.toStr = function () {
  182. var str = this.form;
  183. var shift = 0;
  184. for(var i=0; i<str.length; i++) {
  185. if(this.separators.hasOwnProperty(i)) {
  186. str = str.substring(0, i+shift) + '|' + str.substring(i+shift);
  187. shift++;
  188. }
  189. }
  190. return str;
  191. };
  192.  
  193. }
  194.  
  195.  
  196. function permAlone(str) {
  197. var reps = getReps(str);
  198. var aNumber;
  199. var xNumber = str.length; //xxxxxxx
  200. var numberByForms = factorial(str.length);
  201. var currentForm;
  202. var goodForms = [];
  203.  
  204. var possibleGoodForms = [];
  205.  
  206. reps.sort(function(a,b){ //seem to optimize
  207. return a < b;
  208. });
  209.  
  210. currentForm = new Form(0, xNumber, {});//xxxxxxx
  211. currentForm.firstPossibleGoodForm();
  212. currentForm.number = numberByForms; // 7!=5040
  213. possibleGoodForms.push(currentForm);
  214.  
  215.  
  216. for(var i = 0; i<reps.length; i++) {
  217. aNumber = reps[i];
  218. xNumber -= aNumber; //(aaaxxxx)
  219. numberByForms /= binomial(xNumber+aNumber, aNumber); // (7!/3βŠ‚7)
  220.  
  221. // We replace each possible good forms by their sub-forms.
  222. var newPossibleGoodForms = [];
  223. for(var j = 0; j<possibleGoodForms.length; j++) {
  224. var separators = possibleGoodForms[j].subFormsSeparators();//noprotect
  225. var tmp = [];
  226.  
  227. currentForm = new Form(aNumber,xNumber,separators);
  228.  
  229. var ok = currentForm.firstPossibleGoodForm();
  230. if(!ok) {
  231. currentForm = null;
  232. }
  233. while(currentForm !== null) {
  234. currentForm.number = numberByForms;
  235.  
  236. if(currentForm.isPerfect()) {
  237. // if the form is perfect we don’t have to consider it again
  238. tmp.push(currentForm);
  239. goodForms.push(currentForm);
  240. } else {
  241. tmp.push(currentForm);
  242. newPossibleGoodForms.push(currentForm);
  243. }
  244. currentForm = currentForm.nextPossibleGoodForm();
  245. }
  246. //if((i===1)&&(j===0)){
  247. // return [possibleGoodForms[j], tmp];
  248. //}
  249. }
  250. possibleGoodForms = newPossibleGoodForms;
  251. }
  252.  
  253. // All forms are good forms at the end
  254. goodForms = goodForms.concat(possibleGoodForms);
  255.  
  256. return goodForms.reduce(function(acc, form){
  257. return acc + form.number;
  258. },0);
  259. }
  260.  
  261.  
  262. permAlone('aaaaeeebbfgh');
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement