Entender la respuesta del usuario

Es muy normal equivocarse al introducir texto en una aplicación, tanto por faltas de ortografía como no siendo precisos. Por ejemplo, para la definición “grab my attention”, podría escribir “grab the attention”.

Desarrollando un juego con Jorge donde el usuario tiene que escribir la definición de una palabra he buscado cómo implementar la comprobación de la respuesta que da el usuario para no ser tan estrictos como “Si es la respuesta exacta recibe puntos, si se ha equivocado en algún carácter, la ha pringado”.

He empezado por determinar cuáles serán los criterios para que una respuesta sea válida o no:
Si la definición es sólo 1 palabra, qué menos que el usuario escriba la palabra exacta.
Si la definición son 2 palabras, una tiene que ser exacta y otra como mucho puede tener 3 caracteres equivocados. Ej. Siendo la definición “starting point” sería correcto introducir “start point”.
Si la definición tiene más de 2 palabras, 2 de cada 3 palabras tiene que tener como mucho 1 equivocación. Ej. Para la definición “the main points (of an argument etc)”, sería incorrecto “da main points of a row”.

Para calcular las equivocaciones entre dos palabras, mido la distancia Hamming, algoritmo al que le he añadido el caso especial que es olvidar un carácter. En vez de escribir “attention” se escribe “atention”. Con distancia Hamming la diferencia sería de 7 ya que “tention” no coincide con “ention”. Para evitar esto, cuando se dan dos errores consecutivos se elimina el primer carácter erróneo. Así. se compararía “ention” con “ention” y el resultado sería sólo 1 error (la t que falta) que es más razonable.

Hay que tener en cuenta que no se compara palabra a palabra si no frase a frase y las palabras pueden no tener el mismo orden o puede que falte alguna. Por ello, para cada palabra de la definición se calcula la distancia con cada palabra de la respuesta y se obtiene una matriz de distancias de la que interesa el mínimo por columnas que da como resultado una distancia frase a frase. En el ejemplo, “grab my attention” es la definición.

Imagen

Para separar la definición y la respuesta en palabras utilizo el método split() de String con la expresión regular \\s\\W*|\\W\\s* habiendo antes convertido los caracteres con tildes en caracteres sin tilde utilizando la clase java.text.Normalizer.

Dado que una palabra puede tener varias definiciones, la respuesta tiene que compararse con cada definición. En cuanto se encuentre una comparación definición-respuesta donde la respuesta cumple los criterios se acepta y el usuario recibe sus puntos 🙂

Como resumen del algoritmo:
Para cada definición se compara la definición con la respuesta del usuario.
Para cada palabra de la definición se obtiene la distancia con cada palabra de la respuesta.
De la matriz de distancias obtenida se calcula el mínimo por columnas.
Se comprueba si este mínimo satisface los criterios, si es así, se acepta la respuesta si no, se continúa con la siguiente definición.

Estoy depurando y arreglando este código conforme añado definiciones al test para probarlo. Puedes echarle un vistazo y sugerirme errores al introducir la respuesta que se podrían cometer y que sería exagerado penalizarlos.

Por último, algunas preguntas por si quieres comentar:
¿Son demasiado permisivos los criterios para determinar si una respuesta es válida?
¿Es un terrible rollo esta entrada?

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s