Recursión 1
Permutación con repetición
by Juan Manuel Cruz
November 26, 2017
HTML
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<input type="text" v-model="entrada" @keyup="permute">
<p style="color: red;" v-show="entrada.length > 7">
Cuidado! Las permutaciones crecen muy rápido y esto puede agotar los recursos de tu equipo
</p>
<p v-show="totalPermutations">Número total de permutaciones: {{ totalPermutations }}</p>
<div class="grid" v-if="permutaciones.length">
<p v-for="p in permutaciones">{{ p }}</p>
</div>
<p v-else>Ingrese algo en el campo de texto</p>
</div>
CSS
.grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
JavaScript
const factorial = (n, acc = 1) => n < 2 ? acc : factorial(n - 1, n * acc)
const reducer = (c, x) => {
if (Object.keys(c).includes(x)) c[x] += 1
else c[x] = 1
return c
}
const string_to_array = x => typeof x === 'string' ? x.split('') : x
const number_to_string = x => typeof x === 'number' ? '' + x : x
const key_values = x => string_to_array( number_to_string( x ) ).reduce(reducer, {})
var app = new Vue({
el: '#app',
data: {
entrada: '',
permutaciones: []
},
computed: {
keyedValues () {
return key_values(this.entrada)
},
fullLength () {
return this.entrada.length
},
totalPermutations () {
if (!this.entrada.length) return 0
const values = Object.values(this.keyedValues)
return factorial(this.fullLength) / values.reduce((c, x) => c * factorial(x), 1)
},
orderedKeys () {
return Object.keys(this.keyedValues).sort()
}
},
methods: {
permute () {
this.permutaciones = []
let str = this.orderedKeys.join('')
let count = this.orderedKeys.map(x => this.keyedValues[x])
let result = this.orderedKeys.map(_ => 0)
this.permutator(str, count, result, 0)
},
permutator (str, count, result, level) {
if (this.permutaciones.length === this.totalPermutations) return;
if (level === this.fullLength) this.permutaciones.push(result.join(''))
else str.split('').forEach((character, index) => {
if (!count[index]) return;
result[level] = character
count[index] -= 1
this.permutator(str, count, result.slice(0), level + 1)
count[index] += 1
})
}
}
})