¿Cómo escribo un algoritmo para el problema de las 100 puertas?

Una puerta se abre o cierra solo cuando la identificación del estudiante es un divisor del número de puerta. Entonces, para que una puerta permanezca cerrada, debe tener un número par de divisores.

Si una puerta tiene factorización prima [math] p_1 ^ {a_1} p_2 ^ {a_2} \ dots p_n ^ {a_n}, [/ math] el número de divisores es [math] (a_1 + 1) (a_2 + 1) \ puntos (a_n + 1) [/ math]. Esto se debe a que para elegir un divisor, debe elegir cuántos de cada factor primo deben estar en el divisor, y la cantidad de opciones que tiene depende del exponente del factor primo. Por ejemplo, el número [matemáticas] 162 = 2 ^ 1 \ cdot 3 ^ 4 [/ matemáticas] tiene 10 = 2 * 5 divisores:

  Número de 2 Número de divisor de 3
 0 0 1
 0 1 3
 0 2 9
 0 3 27
 0 4 81
 1 0 2
 1 1 6
 1 2 18
 1 3 54
 1 4 162

Se sigue que una puerta está cerrada si alguno de los exponentes en la factorización prima es impar. Entonces, las puertas abiertas son los números cuadrados, es decir, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100. El código para esto se ve así

  >>> [i * i para i en el rango (1, int (sqrt (100)) + 1)]
 [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

El código se ejecuta en [math] O (\ sqrt {n}) [/ math].

No necesita un algoritmo para esto, hay una solución de forma cerrada fácil

[matemáticas] \ left \ lfloor {\ sqrt {n}} \ right \ rfloor [/ math]

En este caso [math] \ left \ lfloor {\ sqrt {100}} \ right \ rfloor = 10 [/ math]

Razonamiento: cada puerta X será activada (si está abierta y luego cerrada, y viceversa) por el estudiante Y si Y es un factor de X.

La cantidad de veces que se activará una puerta será igual a la cantidad de factores de X. Si el número de factores es par, se cerrará, si es impar, se abrirá.

Por lo tanto, solo necesitamos encontrar el número de números entre 1 y 100 (inclusive) que tienen un número impar de factores.

Si recuerdas de la escuela secundaria, los factores vienen en pares, ya que si a es un factor de x, entonces a veces b es igual a x , es decir, [matemáticas] a \ veces b = x [/ matemáticas]. Ahora, b es también por la misma definición un factor de x.

Por ejemplo, para 10 los factores son 1, 2, 5 y 10. Aquí 1 y 10 forman un par y 2 y 5 forman un par, ya que [matemáticas] 1 \ veces 10 = 2 \ veces 5 = 10 [/ matemáticas]

Entonces, ¿qué números pueden tener un número impar de factores si los factores vienen en pares?

Cuadrados perfectos.

Los cuadrados perfectos tienen un factor, la raíz cuadrada, cuyo compañero es el mismo número. Por ejemplo, los factores de 16 son 1, 2, 4, 8, 16. 16 y 1 son un par, 2 y 8 son un par que deja 4 .

Entonces, todo lo que tenemos que hacer para contar el número de cuadrados perfectos entre 1 y 100.

No quiero parecer condescendiente, pero esto no requiere tanto un “algoritmo” como un uso básico y directo de una declaración de control muy común, que es el for bucle

Primero, prepara las puertas. Las matrices están indexadas a cero, lo que significa que el primer elemento de una matriz está en el índice 0, por lo que asignaré 101 puertas y simplemente no usaré el 0. Eso facilitará razonar sobre las puertas 1 a 100 sin tener que preocuparse por la diferencia de 1.
Las puertas se representarán como una matriz de enteros, donde un valor de 0 significa cerrado y un valor de 1 significa abierto.

 int doors[101]; int i; for (i = 1; i <= 100; i++) doors[i] = 0; // doors start closed 

(Hay muchas alternativas a lo anterior, pero supongo que solo servirán para confundirte. int doors[101] = { 0 }; , memset(doors, 0, 101 * sizeof(int)); , y existen muchos otros equivalentes para inicializar todas las puertas como cerradas. Si compila con -std=c99 , es decir, utilizando el estándar C99 para C, puede inicializar i dentro del for loop también, si quieres: for (int i = 0; i < 101; i++) .)

Luego, itera sobre los estudiantes y las puertas para abrir y cerrar. Esto toma dos for bucles, y puede ordenarlos de la forma que desee:

  1. Cada estudiante abre las puertas que son un múltiplo de su identificación.
     int door_id, student_id; for (student_id = 1; student_id <= 100; student_id++) { for (door_id = student_id; door_id <= 100; door_id += student_id) { if (doors[door_id] == 0) { // if the door is closed, open it doors[door_id] = 1; } else { // if the door is open, close it doors[door_id] = 0; } // any of the following would also suffice: // doors[door_id] = !doors[door_id]; // doors[door_id] = 1 - doors[door_id]; } } 
  2. Cada puerta es abierta por los estudiantes cuyos identificadores pueden dividir equitativamente la identificación de la puerta.
     int door_id, student_id; for (door_id = 1; door_id <= 100; door_id++) { for (student_id = 1; student_id <= 100; student_id++) { if (door_id % student_id == 0) { // ie the remainder of the division (door_id / student_id) is 0 doors[door_id] = !doors[door_id]; // or any of the aforementioned equivalents } } } 

Finalmente, cuente el número de puertas abiertas. Recuerde que un valor de 1 significa una puerta abierta.

 int open_doors = 0; for (door_id = 1; door_id <= 100; door_id++) if (doors[door_id] == 1) open_doors += 1; 

(Como antes, hay muchas formas equivalentes de escribir esto. Podría excluir el == 1 , por ejemplo, o escribe ++ lugar de += 1 )
Y entonces probablemente quieras imprimir este número:
printf("There are %d open doors.\n", open_doors);

Recuerde poner todo esto en un Definición de la función int main(void) que termina con return 0; y #include en la parte superior del archivo.

Aquí hay un programa completo que combina todo lo anterior que imprimirá las puertas abiertas y cuántas son:

 #include  int main(void) { int doors[101] = { 0 }; int student_id, door_id; for (student_id = 1; student_id <= 100; student_id++) for (door_id = student_id; door_id <= 100; door_id += student_id) doors[door_id] = !doors[door_id]; int open_doors = 0; for (door_id = 1; door_id <= 100; door_id++) if (doors[door_id]) { printf(" %d", door_id); open_doors++; } printf("\nopen doors: %d\n", open_doors); return 0; } 

Cuando se compila y ejecuta, esto generará:

  1 4 9 16 25 36 49 64 81100
 puertas abiertas: 10 

Tenga en cuenta también que hay formas más inteligentes de resolver este problema que toda esta iteración. Pero solicitó una forma programática para hacerlo, y supongo que lo está haciendo para practicar la programación básica, por lo que esta es probablemente la solución que se le solicita.

Hola :

  #include 
 #include 
 #define TAMAÑO 100
 #define CERRADO false

 int main (nulo) {
	 puertas de bool [TAMAÑO];
	 para (int i = 1; i 
    

En Haskell

 import Data.List map (1+) $ findIndices odd $ map sum $ transpose $ map (take 100) [cycle $ replicate n (0 :: Int) ++ [1] | n <- [0..99]] 

en php la respuesta se ve así:

   'cerrado', 'cerrado' => 'abierto');

 $ puertas = array_fill (1, 100, 'cerrado');
 for ($ pass = 1; $ pass <= 100; $ pass ++) {
	 para ($ nr = 1; $ nr <= 100; $ nr ++) {
		 if ($ nr% $ pass == 0) {
			 $ puertas [$ nr] = $ estado [$ puertas [$ nr]];
		 }
	 }
 }

 para ($ x = 1; $ x <= 100; $ x ++) {
	 echo "La puerta {$ x} es {$ puertas [$ x]};";
 }
 ?> 

More Interesting

¿Cuánto tiempo / horas debo pasar todos los días para ser un buen programador de Java para poder resolver estructuras de datos y algoritmos con ese lenguaje en el futuro?

No soy bueno en algoritmos, pero estoy tratando de descubrir algo. ¿Cuáles son algunas técnicas o libros o alguna sugerencia?

¿Cuándo debería mirar la solución de algún problema algorítmico?

¿Para qué se usan realmente los algoritmos?

Como principiante, ¿debería leer el libro CLRS antes de comenzar con Interviewbit?

¿Cuáles son algunos de los algoritmos / estructuras de datos que son útiles en la vida real?

Cómo dominar algoritmos, estructuras de datos y desarrollar un enfoque de resolución de problemas

Como estudiante universitario, ¿debería centrarme más en aprender estructuras de datos y algoritmos o aprender tecnologías como aplicaciones, web, desarrollo de iOS, etc.?

¿Cuáles son algunos de los mejores algoritmos?

Cómo comenzar a aprender cómo crear algoritmos de comercio Quant en Java

¿Por qué el método de ordenación Javascript organiza los números de una matriz en orden ascendente con [código] (a - b) [/ código] y descendente con [código] (b - a) [/ código]?

Cómo implementar este algoritmo usando Matlab

¿Cuáles son los algoritmos de nivel básico con los que debemos comenzar y cuáles son los algoritmos avanzados que debemos estudiar?

¿Cuál es el mejor algoritmo para encontrar la ruta más corta en un gráfico orientado, donde algunos bordes están bloqueados y las teclas están en algún lugar de los nodos?

¿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?