Estoy aprendiendo js y tengo problemas con un problema que encontré en Codewars.
Necesito calcular cuántos números que contienen solo dígitos binarios existen entre 1 y un número aleatorio n. Por ejemplo, si n es 20, hay 3 de esos números: 1, 10, 11;
He escrito una solución que funciona en codepen, pero Codewars me dice que es demasiado ineficiente para aceptarla. No puedo pensar en nada más que pueda hacer para optimizarlo. ¡Gracias de antemano por su ayuda!
function incompleteVirus(n) { let countInMemory = 0; let isBinary = true; // Loop through all numbers below and including n for (let i = 1; i <= n; i++) { let strCurrNum = String(i); // Iterate through all digits in the current number for (const digit of strCurrNum) { let numDigit = Number(digit); // Check if each digit is binary; if not, exit loop if (numDigit > 1) { isBinary = false; break; } else { isBinary = true; } } // Update memory count if (isBinary) { countInMemory += 1; } } return countInMemory }EDITAR: Estoy vinculando el kata aquí si alguien está interesado.
Ese fue un kata interesante para hacer, y me divertí resolviéndolo.
Mi enfoque fue verificar algunos ejemplos y analizar los dígitos, en lugar de los números enteros.
Por ejemplo:
Así que esto es lo que entendí de ese patrón:
Cuando un dígito es mayor que 1 , reemplaza todos los dígitos de la izquierda con 1 s.
De lo contrario (si el primer dígito es 0 o 1 ), reemplace cualquier dígito que no sea 0 o 1 a 1
Entonces comencé a construir una expresión regular.
Para el primer caso, necesitaría un lookbehind positivo: (?<=[2-9].*)\d .
El segundo caso es un simple [^01]
Y dado que para ambos casos, los dígitos deben reemplazarse por 1 s, solo se necesita un solo replace .
La instrucción resultante, incluida la conversión a decimal, es:
parseInt(n.replace(/(?<=[2-9].*)\d|[^01]/g, 1), 2)La respuesta de @Seblor es la más directa.
Pero en caso de que tenga curiosidad acerca de una solución sin expresiones regulares, aquí hay una opción con un bucle foreach más tradicional:
function bins(n) { let exx = false let acc = 0 n.toString().split('').forEach((d, i, arr) => { // exx will be true from the moment any digit exceeds 1 exx ||= d > 1 // if the current digit is positive, acc will add up a power of two acc += (exx || ~~d) && (2 ** (arr.length - i - 1)) }) return acc } console.log(bins(1112))