Estamos buscando una aguja en una pila sin usar algoritmos conocidos


¿Qué método para encontrar una aguja es más rápido? ¿Clasificar a través de una pajita o buscarla accidentalmente?

Creo que la mejor manera es experimentar, desafortunadamente no tengo un pajar, pero tengo conocimientos básicos de programación, un microcontrolador Arduino, un entorno conveniente para escribir código, para que todos puedan repetirlo.

Paso uno "Comprender"


¿Qué datos quiero recibir? Tiempo dedicado a encontrar la solución correcta. La única ejecución no es adecuada debido a los detalles del experimento, debe verificar el método varias veces, luego el tiempo que me interesa es promedio. Me decidí por esto. El siguiente paso es cuántas y qué variables declarar. Necesitamos una variable separada para cada método para almacenar la suma de veces, llamémosla:

"Time_poslMetod" y "Time_randMetod".

Necesita una constante en el número de iteraciones:

#define Iter 1000.

El valor de salida se obtiene dividiendo el primero por el número de iteraciones.

#define Iter 10000 #define cell 100 uint8_t potenArr[cell]; //  uint8_t needle = 0; //  uint32_t startTime = 0; //    uint32_t endTime = 0; //    uint32_t calculationStartTime = 0; uint32_t calculationEndTime = 0; uint32_t Time_poslMetod = 0; uint32_t Time_randMetod = 0; 

Paso dos "escribir código"


El ciclo For gestiona el número de iteraciones, dentro de él "arrojaremos" la aguja al pajar, realizaremos una búsqueda, mediremos el tiempo para cada método por separado, guardaremos el tiempo en una variable "global" (Time_poslMetod / Time_randMetod) (para el futuro).

  //   Iter  for(uint32_t j = 0; j <= Iter; j++){ //      cleanArr(); //     needle = random(cell + 1); potenArr[needle] = 1; //          poslMetod(); randMetod(); } 

Así son mis métodos.

Método secuencial:

 void poslMetod(){ startTime = millis(); for(uint16_t i = 0; i < cell; i++){ if(potenArr[i] == 1){ endTime = millis() - startTime; break; } } Time_poslMetod += endTime; } 

Antes del comienzo, memorizamos el tiempo y luego lo restamos del momento en que finalizó la búsqueda. Recorremos la matriz (stack) desde el primer elemento hasta el último. Cuando encontremos la aguja, escriba la hora, complete la búsqueda, agregue la hora a la variable "global" (Time_poslMetod) y salga del método.

Método aleatorio

 void randMetod(){ startTime = millis(); for(;;){ uint16_t r = random(cell + 1); if(potenArr[r] == 1){ endTime = millis() - startTime; break; } } Time_randMetod += endTime; } 

La diferencia es que verificamos un elemento aleatorio de la matriz (un lugar en la pila), confiamos en la suerte hasta que tenemos suerte y encontramos una aguja , por lo que usamos un bucle infinito, lo principal es que tenemos una condición de salida, por lo que no nos preocupamos. Cuando encontremos la aguja , registremos el tiempo, completemos la búsqueda, agreguemos el tiempo a la variable "global" (Time_randMetod) y salgamos del método.

Puede notar que el método no nos garantiza ninguna garantía de que sea más rápido, de esta manera se ve aún más lento, porque si la suerte no está de nuestro lado, podríamos hacer más de 100 comprobaciones de los lugares de la pila y fallar, en ese momento como en un método secuencial de 100 verificaciones significaría que verificamos toda la pila y definitivamente habríamos encontrado una aguja que pasa el tiempo máximo para este método. Sin embargo, estoy a favor del experimento, así que continuemos.

Poniendo todo junto, puliendo el código, haciendo que la salida sea conveniente para la comprensión:

Código completo
 #define Iter 10000 #define cell 100 uint8_t potenArr[cell]; //  uint8_t needle = 0; // ,         uint32_t startTime = 0; //    uint32_t endTime = 0; //    uint32_t calculationStartTime = 0; uint32_t calculationEndTime = 0; uint32_t Time_poslMetod = 0; uint32_t Time_randMetod = 0; void poslMetod(); void randMetod(); void cleanArr(); void DataOutPrint(); void setup() { randomSeed(analogRead(A0)); Serial.begin(115200); } void loop() { Time_poslMetod = 0; Time_randMetod = 0; Serial.println(" "); Serial.println("Start"); calculationStartTime = millis(); //   Iter  for(uint32_t j = 0; j <= Iter; j++){ //      cleanArr(); //        needle = random(cell + 1); potenArr[needle] = 1; //           poslMetod(); randMetod(); } //       DataOutPrint(); delay(2000); } void poslMetod(){ startTime = millis(); for(uint16_t i = 0; i < cell; i++){ if(potenArr[i] == 1){ endTime = millis() - startTime; break; } } Time_poslMetod += endTime; } void randMetod(){ startTime = millis(); for(;;){ uint16_t r = random(cell + 1); if(potenArr[r] == 1){ endTime = millis() - startTime; break; } } Time_randMetod += endTime; } void cleanArr(){ for(uint16_t i = 0; i < cell; i++){ potenArr[i] = 0; } } void DataOutPrint(){ calculationEndTime = (millis() - calculationStartTime)/1000; float OUTposl = (float)Time_poslMetod/Iter; float OUTrand = (float)Time_randMetod/Iter; Serial.println(" "); Serial.print("Number of iterations = "); Serial.println(Iter); Serial.print("Time for calculate (sec) = "); Serial.println(calculationEndTime); Serial.print("Posledovatelniy metod - AverageTime (ms) = "); Serial.println(OUTposl,3); Serial.print("Randomniy metod - AverageTime (ms) = "); Serial.println(OUTrand,3); } 


Paso tres "Análisis de resultados"


Obtenemos:



Honestamente, estoy sorprendido por los resultados. Después de haber apostado el dinero a que los tiempos estarán cerca, perdería.

Justo lo que temía sucedió, la suerte se alejó de mí (nosotros). Eso sería verificar cómo hubieran sido las cosas si hubiéramos seleccionado cada celda siguiente en la pila, no hubiéramos seleccionado las ya marcadas. Mientras tanto, tendremos en cuenta que estudiar programación, matemáticas y ciencias exactas es útil para reducir el tiempo de las aburridas operaciones de rutina, dejando tiempo para algo divertido.

Source: https://habr.com/ru/post/439336/


All Articles