¿Qué es una expresión regular que devolverá falso cuando una letra determinada aparece más de n veces?

Supongo que desea una expresión regular que verifique toda la línea, y desea que acepte una cadena solo si cierta letra aparece menos de N veces en la cadena.

Mira, las expresiones regulares se llaman regulares, porque pertenecen a la clase de lenguajes regulares. Los idiomas regulares son algo limitados, pero su solicitud (aceptar algo solo si la letra aparece menos de N veces) está dentro de los límites.

Primero, echemos un vistazo al Autómata finito determinista que aceptaría dicha cadena:

Aquí “q” es la letra que queremos limitar, Σ es el alfabeto completo que estamos aceptando (por ejemplo, cualquier carácter). Σ – q es un alfabeto completo sin la letra. Los estados subrayados son estados aceptados. Aceptamos como máximo 5 q’s.

Puede ver que DFA para este problema es realmente simple: solo dibuja N + 1 estados. Cada estado “cuenta” las ocurrencias de la letra (“q”) en la cadena que estamos procesando. Comenzamos en 0, porque inicialmente hemos visto 0 letras (“q” s). Si alcanzamos el estado N + 1, sabemos que la letra apareció demasiadas veces, por lo que dejamos de aceptar (el estado N + 1 es el único estado que no es aceptado. No puede salir de este estado) .

Ahora volvemos a crear una expresión regular. Después de mirar este DFA, creo que es más fácil ver cómo podríamos querer crear una expresión regular de este tipo (en la expresión regular, nuestra letra es “h” y nuestra N es 6):

^ ([^ h] * h) {0,6} [^ h] * $

Primero tenemos “^”. Esto significa que queremos asegurarnos de tener el comienzo de nuestra cadena. De lo contrario, obtendríamos coincidencias parciales (por ejemplo, en la cadena “hhhhhhhhho”, “o” coincide con nuestra expresión regular).

A continuación, tenemos el grupo “([^ h] * h)”. Esto significa que queremos ver cualquier cantidad de caracteres que no sean h. Entonces, por ejemplo, podemos aceptar “h”, “addh” u “ooh”, pero no cualquier cosa que tenga más de una h, por ejemplo, “hoh”.

Luego, tenemos “{0,6}” que nos dice que el grupo que acabamos de mencionar debe aparecer al menos 0 veces (por lo que también aceptamos cadenas vacías), pero como máximo 6 veces.

Finalmente, tenemos [^ h] * nuevamente. Esto es para permitir que la cadena termine en cualquier letra, no solo h.

Y después de eso, terminamos la línea con $.

Tal expresión regular es bastante simple y no requiere búsquedas.

Aquí está la solución (y la captura de pantalla adjunta del código que se ejecuta en la consola de JavaScript)

(/ (^ | [^ h]) h {3,6} ([^ h] | $) /). test (”);
// falso

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘O ‘);
// falso

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Oh ‘);
// falso

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Ohh ‘);
// falso – menos de 3 veces

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Ohhh ‘);
// cierto

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Ohhhh ‘);
// cierto

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Ohhhhh ‘);
// cierto

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Ohhhhhh ‘);
// cierto

(/(^|[^hfont>)h{3,6}([^hfont>|$)/).test(‘Ohhhhhhh ‘);
// falso – más de 6 veces

Versión 1, que es lo que tiene: “Quiero 3–6 h seguidas”.

La versión 2 sería un poco mejor: “Quiero 3–6 h seguidas, seguido de algo que no sea una h”. Algo así como / h {3,6} [^ h] /. Eso no coincidiría con “Ohhh” al final de su cadena.

La versión 3 está más cerca: “3–6 h seguidas, no seguidas de una h”. Eso es negativo. Eso sería / h {3,6] (?! h) /. (Confesión: cada vez que golpeo hacia adelante / hacia atrás positivo / negativo, tengo que buscar la sintaxis).

Estamos realmente cerca ahora. Pero eso todavía coincidirá con Ohhhhhhh (porque coincide con las 6 h finales en lugar de las 6 iniciales).

Entonces, lo que creo que realmente quieres: “3–6 h seguidas, no seguidas de una h ni precedidas por una h”. Eso tiene una mirada negativa hacia atrás y una negativa hacia adelante. Algo así como / (?

Un enfoque es probar dos veces. La primera vez que realiza la prueba para decir 7 o más ocurrencias de la letra. La segunda vez que prueba el rango de ocurrencias deseado. La segunda prueba solo se realiza si la primera prueba falla.

Por ejemplo, si desea atrapar solo de 3 a 6 ocurrencias de la letra h en una palabra, puede usar los dos patrones siguientes:

[\ S- [h]] * h {7,} [\ S- [h]] *

[\ S- [h]] * h {3,6} [\ S- [h]] *

Puede usar esta expresión regular (supongo que no está preguntando sobre 6 letras consecutivas)

^ ((?: [^ h] * h) {3,6} [^ h] *) $

Desglose de expresiones regulares

^ # Comienzo de cadena
(#Inicio del grupo de captura
(?: [^ h] * h) # Coincide con cualquier otra cosa que no sea h (o su letra de elección y luego la letra que desea)
{3,6} # Repita el proceso anterior entre 3 y 6 veces
[^ h] * # Después de eso puede ser cualquier otra letra excepto h
) # Fin del grupo de captura
$ # Fin de cadena

Debe usar un lookbehind y uno lookahead si su motor regexp los admite. El aspecto posterior asegura que la coincidencia no salte más allá de los caracteres h al comenzar la coincidencia, y la anticipación asegura que el siguiente carácter no sea un carácter h.

O bien, podría hacerlo más fácil para usted y usar algo distinto de una expresión regular para el cheque.

(?: ^ | [^ h]) h {3,6} (? = [^ h] | $)

Crédito al Sr. Martin

More Interesting

¿Cuál será el código C si quiero imprimir todos los elementos ingresados ​​en orden inverso sin usar matrices?

¿Cuál es la diferencia entre el algoritmo codicioso y la programación dinámica? ¿Es un programa codicioso un subconjunto de programación dinámica?

¿Cuáles son algunas de las preguntas de cadena que se hacen comúnmente en una entrevista técnica?

¿Cuál es una buena explicación de la asignación de Dirichlet latente?

¿Existen algoritmos que puedan determinar la convergencia o la falta de ella para cualquier serie arbitraria que se pueda expresar en notación de suma estándar?

Cómo ponerse al día con las matemáticas necesarias para poder comprender y analizar algoritmos si no sé sobre cosas como el registro

Cómo aprender fácilmente el pseudocódigo del algoritmo

¿Qué estructuras de datos y algoritmos deben conocer todos los estudiantes de ciencias de la computación / ingeniería?

¿Cómo se usa el algoritmo babilónico?

¿Cómo se implementa la cola prioritaria en C ++? ¿Cómo se hace usando STL?

¿Cuáles son algunos de los principales factores que pueden afectar la velocidad de ejecución de un algoritmo?

Si estoy usando Java para la codificación competitiva, ¿tendré problemas de tiempo más tarde por parte de jueces en línea cuando me sumerja en estructuras de datos y algoritmos?

¿Cuál es el mejor libro sobre estructuras de datos y algoritmos en Java?

¿Es necesario el conocimiento de algoritmos clásicos para convertirse en un experto en inteligencia artificial?

¿De qué se trata el algoritmo Google Hawk?