He resuelto el problema Contar las caras sonrientes :
Dada una matriz (arr) como argumento, complete la función countSmileys que debería devolver el número total de caras sonrientes.
Reglas para una cara sonriente:
- Cada cara sonriente debe contener un par de ojos válidos. Los ojos se pueden marcar como
:o;- Una cara sonriente puede tener nariz, pero no necesariamente. Los caracteres válidos para una nariz son
-o~- Cada rostro sonriente debe tener una boca sonriente que debe marcarse con
)oDNo se permiten caracteres adicionales a excepción de los mencionados.
Ejemplos de caras sonrientes válidas:
:) :D ;-D :~)Caras sonrientes no válidas:;( :> :} :]Ejemplo
countSmileys([':)', ';(', ';}', ':-D']); // should return 2; countSmileys([';D', ':-(', ':-)', ';~)']); // should return 3; countSmileys([';]', ':[', ';*', ':$', ';-D']); // should return 1;Nota
En caso de una matriz vacía, devuelva 0. No se le probará con una entrada no válida (la entrada siempre será una matriz). El orden de los elementos de la cara (ojos, nariz, boca) siempre será el mismo.
Luego, cuando reviso las soluciones, encuentro que muchas personas usan expresiones regulares. Entonces quiero escribir una máquina de estado para implementar expresiones regulares y resolver este problema. Pero fracasé. Este es mi código:
function countSmileys(smileys) { let state = smileyHasValidEye; return smileys.filter(smiley => { for (let s of [...smiley]) { state = state(s); } return state === true; }).length; } function smileyHasValidEye(s) { if (s === ':' || s === ';') { return smileyHasValidNose; } return smileyHasValidEye; } function smileyHasValidNose(s) { if (s === '-' || s === '~') { return smileyHasValidMouth; } return smileyHasValidMouth(s); } function smileyHasValidMouth(s) { if (s === ')' || s === 'D') { return true; } return; } console.log(countSmileys([':)', ';(', ';}', ':-D']));Y el error que me sale es:
state = state(s); ^ TypeError: state is not a function Luego depuré mi código y encontré que el procedimiento no ingresa a la función smileyHasValidNose . Entonces no sé la razón.
El problema es que realmente no restablece state entre emoticonos. Entonces, el próximo estado sonriente será true y no podrá llamarlo (no es una función).
Podría usar una variable local para el state que lo restablece a la primera función (el primer paso).
function countSmileys(smileys) { let firstStep = smileyHasValidEye; return smileys.filter(smiley => { let state = firstStep; for (let s of [...smiley]) { state = state(s); } return state === true; }).length; } function smileyHasValidEye(s) { if (s === ':' || s === ';') { return smileyHasValidNose; } return smileyHasValidEye; } function smileyHasValidNose(s) { if (s === '-' || s === '~') { return smileyHasValidMouth; } return smileyHasValidMouth(s); } function smileyHasValidMouth(s) { if (s === ')' || s === 'D') { return true; } return; } console.log(countSmileys([':)', ';(', ';}', ':-D']));Sin embargo, este código generará un error si hay más en la cadena además del emoticón (o una parte del emoticón).
Cambiaría smileyHasValidMouth para que devuelva false si no detecta un emoticón. Solo para ser más consistente aquí...
function smileyHasValidMouth(s) { if (s === ')' || s === 'D') { return true; } return false; }Y ajuste su ciclo para salir antes si encuentra un valor que no es una función.
for (let s of [...smiley]) { state = state(s); if(typeof state !== 'function') return state; } function countSmileys(smileys) { let firstStep = smileyHasValidEye; return smileys.filter(smiley => { let state = firstStep; for (let s of [...smiley]) { state = state(s); if (typeof state !== 'function') return state; } }).length; } function smileyHasValidEye(s) { if (s === ':' || s === ';') { return smileyHasValidNose; } return smileyHasValidEye; } function smileyHasValidNose(s) { if (s === '-' || s === '~') { return smileyHasValidMouth; } return smileyHasValidMouth(s); } function smileyHasValidMouth(s) { if (s === ')' || s === 'D') { return true; } return false; } console.log(countSmileys([':~(', ':>', ':D', ':(', ':o>', ';)', ':)']));