¿Cómo puedo evitar las técnicas de fuerza bruta?

No evites la fuerza bruta, pero aprende a construir y mejorarla.

La resolución de problemas se trata de hacer el trabajo mientras se optimiza el uso de los recursos. Eso incluye no solo el tiempo y las necesidades de almacenamiento del algoritmo, sino también el trabajo que pones para diseñarlo e implementarlo, y quizás aún más importante, el tiempo y el esfuerzo mental que alguien más dedicará a descubrir cómo funciona y si es correcto.

Las soluciones de fuerza bruta suelen ser las más fáciles de diseñar, implementar y comprender, y es por eso que siempre debe probarlas primero. Cuando la fuerza bruta funciona, puedes pasar felizmente a resolver otros problemas. Cuando no lo hace, bueno, probablemente no estés usando lo suficiente. Es una broma. Cuando no funciona, descubres por qué y luego mejoras el algoritmo. Puede encontrar ineficiencias en una implementación mediante la creación de perfiles.

El diseño de algoritmo iterativo es la mejor manera de aprender sobre el problema en cuestión. Casi todos los algoritmos famosos son mejoras a los de fuerza bruta o se basan en ideas sobre por qué los de fuerza bruta son ineficientes. Tome el algoritmo KMP, por ejemplo, que se basa en una observación sobre la búsqueda de cadenas ingenua.

Aquí hay algunas citas que capturan estos pensamientos de manera sucinta:

No pienses demasiado, a menos que sea absolutamente necesario. (Klaus Sutner)

La optimización prematura es la fuente de todos los males. (Don Knuth)

La ingeniería se realiza con números. El análisis sin números es solo una opinión. (Dave Akin)

Una cosa simple que puede hacer es recorrer su código en un depurador, y cada vez que se encuentre pensando “¡esto es tan tonto!”, Pregúntese: “¿Qué es exactamente lo que sé (tal vez implícitamente) que me permite reconocer la estupidez de los pasos que la computadora sigue servilmente? ”

Por ejemplo, suponga que está construyendo un corrector ortográfico (o un programa de juego de scrabble que necesita verificar la validez de las palabras formadas por los movimientos del jugador humano) dirigido a hardware de baja especificación (procesador lento, RAM lenta). Comienza con una búsqueda lineal, encuentra que es demasiado lenta, pasa a una búsqueda binaria (mejor, pero aún demasiado lenta), ¿qué sigue? Después de recorrer el código, puede notar que una gran ventaja que tiene sobre la computadora es su conocimiento incorporado de las posibles transiciones de una letra a la siguiente que son realmente plausibles / posibles en su idioma de destino. ¿Quizás hay una manera de codificar ese conocimiento de alguna manera “compilando” su léxico en una estructura de datos optimizada que eliminaría por completo la búsqueda? ¿Tal vez algo parecido a un árbol, con cada nodo representando una letra?

(En este caso, como era de esperar, la estructura de datos que busca ya se ha inventado, se llama Gráfico de palabras acíclicas dirigido, o DAWG para abreviar).

Sin embargo, lo anterior sigue siendo válido como ilustración de uno de los (muchos) posibles caminos por los cuales es posible llegar a este tipo de realización.

Su problema es que no está pensando de manera abstracta. Por “técnicas de fuerza bruta” entiendo que quiere decir que es inepto para encontrar soluciones tolerantes a fallas y de talla única cuando programa. Este tipo de soluciones son críticas porque no puede dar cuenta de cada entrada que utilizará un programa.

La única vez que usaría un enfoque de fuerza bruta cuando programe es cuando sé que puedo dar cuenta de cada caso / cada entrada que sé que mi programa tendrá que tratar.

Sugeriría lo siguiente:

  • Familiarícese con los conceptos de OOP como: jerarquías de herencia, clases abstractas, interfaces, polimorfismo y encapsulación de datos.
  • Lea sobre los patrones de diseño | Diseño orientado a objetos
  • Lea el código fuente para marcos populares y bien diseñados, como WordPress y jquery.
  • Echa un vistazo a este libro electrónico de algoritmos desde mi dropbox: estructuras de datos y algoritmos.pdf

El punto clave necesario para pasar de una solución de fuerza bruta a una solución “inteligente” es una visión profunda del problema en cuestión. Esto no es necesariamente fácil dependiendo de su experiencia con el dominio del problema.

Puedo dar un consejo general que ayuda en algunos problemas. Al tratar de resolver un problema que se basa en la pregunta de si algo es posible, debe preguntarse “¿Estoy buscando un ejemplo que demuestre que es posible?” O “¿Solo necesito mostrar un argumento de que algo es posible sin tener que mostrar un ejemplo “.

Por ejemplo, suponga que desea escribir un método que determine cuántos subconjuntos se les da un conjunto particular. Una forma de resolverlo es generar todos los subconjuntos y luego contarlos y devolverlos. En este caso es un algoritmo de fuerza bruta. Mirando la pregunta más de cerca, realmente no necesita generar todos los subconjuntos porque el problema solo quiere el número de subconjuntos, por lo que podría aplicar la fórmula matemática que dice que dado un conjunto de tamaño N hay 2 ^ N subconjuntos. Tenga en cuenta que al preguntar qué tipo de valor de retorno está buscando puede cambiar en gran medida su perspectiva sobre cómo resolver el problema.

More Interesting

¿Debería evitarse siempre goto / JMP?

¿Dónde aprendo árboles AVL?

¿Qué algoritmo se puede usar para la predicción de pasajes aéreos?

Tengo conocimiento de estructuras de datos y algoritmos, pero me falta programación competitiva, ¿cómo debo mejorar? ¿Puedo sobrevivir a la competencia de hoy?

¿La evolución biológica es algorítmica?

Cómo demostrar que el camino más corto posible entre dos puntos es una línea recta

¿Cuál es una versión más amigable para principiantes de CLRS para algoritmos de aprendizaje? ¿Estaría rompiendo la entrevista de codificación?

Interacción humano-computadora: ¿Qué tan difícil sería escribir un algoritmo que pudiera identificar similitudes en las expresiones faciales entre dos imágenes tomadas en la cabeza?

¿Aprender la construcción del compilador mejora la habilidad / visión de resolución de problemas de programación? ¿Si es así, cómo? ¿O por qué no?

¿Qué tipo de clasificación es esta?

¿Cuál es la solución a la siguiente relación de recurrencia: [matemáticas] T (n) = 3T (n-1) - 7T (n-2) + 9T (n-3) [/ matemáticas], con las siguientes condiciones iniciales: [ matemática] T (0) = 1 [/ matemática], [matemática] T (1) = 6 [/ matemática], [matemática] T (2) = 7 [/ matemática]. ¿Qué es una expresión para [math] T (n) [/ math] de modo que no haya términos [math] T (i (\ frac {n} {j}) ^ {k}) [/ math] a la derecha ¿lado?

¿Cómo se implementan las tablas hash en el kernel de Linux? ¿Cómo funcionan para diferentes tipos de datos y estructuras?

¿Debo compartir un nuevo algoritmo de clasificación que escribí? ¿Existe algún potencial monetario en un algoritmo? De ser así, ¿cómo capitalizo?

¿Cómo se implementa la estructura de datos establecida en C?

¿Cuál crees que es el algoritmo de aprendizaje automático más inteligente?