Un vector (en JavaScript se dice array) guarda varios valores bajo un solo nombre, en orden. lecturas no es «la luz»: es la serie. Cada valor vive en un índice. El primero es 0, el segundo es 1, y el último es la longitud menos uno. Si hay cuatro lecturas, los índices son 0, 1, 2 y 3. Pedir la casilla 4 es un error, no un cero educado. El laboratorio se para y lo dice. En una placa, leer fuera del array es comportamiento indefinido: a veces basura, a veces un cuelgue. No es una casilla vacía con la que se pueda calcular una media.
El para encaja aquí porque las vueltas se saben: tantas como casillas. para i = 0 hasta v.longitud - 1 entra en todas y en ninguna de más. Escribir hasta v.longitud es el error de esta lección. La condición parece natural («hasta el número de elementos») y se come una casilla que no existe. Por eso la traza se hace con el índice escrito al lado del valor, no solo con la suma.
Dentro del vector todas las casillas de esta práctica son números, las lecturas. Mezclar en la misma serie un texto y un número complica la media: la suma dejaría de ser una suma en cuanto el + encuentre una cadena. Si necesitas el nombre del sensor, no va en la casilla 2: va en otro nombre, o en un objeto, que es la lección siguiente.
Una función es un algoritmo con nombre. Se le pasan parámetros (los datos de entrada de ese subproblema) y devuelve un resultado, o hace un efecto que has decidido limitar. media(v) no debería encender el LED por su cuenta: debería devolver un número. Quien llama, let m = media(lecturas), decide qué hacer con m. Esa separación es la misma descomposición de la lección 23, ahora con una frontera que el lenguaje vigila.
Los parámetros son variables nuevas de la función, no copias mágicas del nombre de fuera. Si el parámetro se llama v, dentro se usa v, no lecturas, aunque al llamar hayas pasado lecturas. Cambiar un número parámetro no cambia la variable de fuera. En este laboratorio los vectores se pasan como el propio vector: si una función escribiera en una casilla, se vería fuera. Por eso una función de media no escribe en las casillas. Calcula y devuelve.
devolver termina la función y entrega el valor. Lo que escribas debajo, en la misma función, no se ejecuta. Sin devolver, la llamada no tiene un número que guardar: el resultado es nulo y la media «desaparece» aunque la suma se hubiera hecho. El error se ve en el entorno: m no es 480, es nulo. 480 es la media de 420, 510, 390 y 600, porque la suma es 1920 y hay cuatro casillas.
420 + 510 = 930
930 + 390 = 1320
1320 + 600 = 1920
1920 ÷ 4 = 480
Si te sale 640, has dividido entre tres: te comiste una casilla o contaste mal la longitud.
1920 ÷ 3 = 640
En el sketch, int lecturas[4] reserva cuatro enteros, y una función int media(int v[], int n) recibe también la longitud, porque un array de C no la guarda solo. En Python, sum(lecturas)/len(lecturas) es la misma idea con la longitud incluida. En JavaScript, lecturas.length. Tres sintaxis, un cuidado: no uses un índice que no esté entre 0 y n-1. El LED sigue fuera de la función de la media. Encenderlo es otra función o el si de siempre, que compara la media, o la última lectura, con el umbral. No metas digitalWrite dentro de media «ya que estamos»: el día que quieras la media para un informe, encenderás un pin sin querer.
El canvas, si dejas el vector en lecturas, dibuja una barra por casilla. La altura no es el pin: es el dato. El pin sigue siendo la decisión posterior. Ejecutar tiene que mostrar m = 480 en el ejemplo. Si no sale, no arregles el 480 a mano en un escribe: arregla el recorrido.
Vector. Serie ordenada bajo un nombre. En JavaScript, array.
Índice. Posición. Empieza en 0. Tiene que ser entero y caber.
longitud. Cuántas casillas hay. El último índice es longitud - 1.
Parámetro. Nombre de la entrada de la función, distinto del argumento con el que llamas.
Argumento. El valor que pasas en la llamada: media(lecturas).
devolver. Cierra la función y entrega un valor a quien llamó.
Efecto. Un cambio fuera de la función, como encender un pin. La media no debería tenerlo.
Fuera de rango. Índice negativo, fraccionario o mayor o igual que la longitud. Es un error.
para i = 0 hasta lecturas.longitud intenta leer la casilla 4. No existe. El mensaje lo dice. Se cambia el hasta por longitud - 1 y la suma pasa a 1920.
420 + 510 = 930
930 + 390 = 1320
1320 + 600 = 1920
Dentro de media alguien escribe el pin. Al pedir la media para el informe de las 18:00 el LED se enciende. Se saca el digitalWrite al algoritmo que llama.
El para empieza en 1. La media usa tres casillas y el 420 desaparece. 510+390+600 = 1500, entre 3 es 500, que casualmente es el umbral y parece «correcto».
510 + 390 = 900
900 + 600 = 1500
1500 ÷ 3 = 500 La traza con índices enseña que falta el 0.
Cada caso es una entrega del avisador del patio del IES Duero (Aranda de Duero). Lee la situación antes de la decisión.
Situación. luz1, luz2, luz3, luz4 y una suma a mano.
No conviene. Porque todavía no hay muchos datos.
Decisión. Guardar el vector y recorrer. La función media no cambia cuando mañana hay ocho lecturas.
Por qué: luz1, luz2, luz3 y luz4 con una suma a mano sirven solo mientras sean cuatro. El algoritmo de la media no depende de cuántas casillas hay, solo de no salirse. El vector se recorre, y añadir una lectura no obliga a inventar luz5.
Situación. El grupo dice que la casilla cero es rara y la salta.
No conviene. Porque en clase se numera desde uno.
Decisión. Recorrer desde 0 y escribir el índice al lado en la tabla.
Por qué: Saltar la casilla cero porque «en clase se numera desde uno» borra una lectura. La media se sesga hacia las horas que quedan, no es un detalle de estilo. El recorrido empieza en 0 y llega hasta la última casilla que existe, sin hueco al principio.
Situación. En el sketch, el array no lleva la longitud encima.
No conviene. Inventar un 4 escrito en tres sitios distintos.
Decisión. Pasar n a la función y usar un solo sitio para el 4, o calcular el tamaño con la fórmula del compilador de C que el IDE ya conoce (sizeof), sin reescribir el número a ciegas.
Por qué: En el sketch la longitud no viaja sola encima del array, y tres cuatros escritos en sitios distintos se desincronizan en cuanto añades una lectura. Se pasa n a la función o se calcula el tamaño en un solo sitio. El 4 repetido a mano no es el tamaño.
Situación. La función devuelve la media y además hace un escribe de depuración que se queda en la entrega.
No conviene. Porque ayuda.
Decisión. Quitar el escribe de la función antes de darla por cerrada, o dejarlo solo en la llamada.
Por qué: Una función que devuelve la media y además escribe un mensaje de depuración mezcla el resultado con el ruido. En una placa, «hablar» a veces se confunde con tocar un pin. El escribe de prueba se quita de la entrega; la función solo devuelve el número.
El problema no cambia: si la luz del patio del IES Duero baja de 500, hay que avisar. Cambia quién ejecuta. El pseudocódigo lo ejecuta el laboratorio de esta página. El sketch lo compilaría el IDE de Arduino hacia la UNO. El fragmento de Python lo ejecutaría una Raspberry Pi con gpiozero, si hubiera placa. Aquí no hay placa.
Con [420, 510, 390, 600] devuelve 480.
420 + 510 = 930
930 + 390 = 1320
1320 + 600 = 1920
1920 ÷ 4 = 480
funcion media(v)
let s = 0
para i = 0 hasta v.longitud - 1
s = s + v[i]
fin
devolver s / v.longitud
fin
El for de C usa i < n, que es lo mismo que hasta n-1 en nuestro para, porque el hasta de aquí incluye el final. return es devolver. El LED no está en esta función.
int lecturas[4] = {420, 510, 390, 600};
int media(int v[], int n) {
long s = 0;
for (int i = 0; i < n; i++) s += v[i];
return s / n;
}
len es la longitud. sum recorre desde el índice 0. El GPIO 18 se decide después, comparando m o la última casilla con el umbral.
lecturas = [420, 510, 390, 600]
def media(v):
return sum(v) / len(v)
m = media(lecturas) # 480
| Índice | Valor | Suma acumulada | ¿Existe? |
|---|---|---|---|
| 0 | 420 | 420 | sí |
| 1 | 510 | 930 | sí |
| 2 | 390 | 1320 | sí |
| 3 | 600 | 1920 | sí |
| 4 | — | — | no |
1920 / 4 = 480.
1920 ÷ 4 = 480
La fila del índice 4 está para que se vea el fallo, no para que se programe. Dividir 1920 entre 3 es el síntoma de haberse dejado una casilla.
1920 ÷ 3 = 640
Cambia el vector a [100, 100, 100, 100]. La media tiene que ser 100.
100 + 100 = 200
200 + 100 = 300
300 + 100 = 400
400 ÷ 4 = 100 Es una prueba tonta y por eso vale: si no sale 100, el recorrido está roto y con los datos del patio no se vería tan claro. Luego vuelve al ejemplo de 480.
Escribe una segunda función maximo(v) que devuelva la mayor lectura, con un si dentro del para. No enciendas el LED dentro. Quien llame puede comparar ese máximo con el umbral si el problema lo pide. El parámetro sigue siendo el vector entero, no una casilla suelta.
En C, el for (int i = 0; i < n; i++) no visita n. Visita 0, 1, …, n-1. Es el mismo conjunto que para i = 0 hasta n - 1 en este laboratorio, donde el hasta sí se incluye. Al traducir, se traduce la condición, no las palabras sueltas.
| Criterio | Aún no | En proceso | Conseguido | Notable |
|---|---|---|---|---|
| Índices | Desde 1 o hasta longitud | A veces | 0 … longitud-1 | Tabla índice-valor |
| Función | Copia de la suma | Sin devolver | Parámetro y devolver | No toca el pin |
| Resultado | Cualquier número | 480 escrito a mano | 480 por el recorrido | Se prueba con otro vector |
| Tipos | Texto en una casilla | Sin mirar | Todas las lecturas son números | La media se guarda en un número |
| Placa | No se menciona | Solo el LED | Array de C y lista de Python, índice 0 | La longitud se pasa o se pide, no se duplica a ciegas |
El vector se recorre desde 0 hasta longitud-1. La función devuelve la media y no enciende nada. 480 es la prueba del ejemplo, no un número que se escriba a mano.
Abre cada pregunta, responde en el cuaderno y después mira la solución. El párrafo «Por qué» es la parte que se estudia.
Respuesta. Porque se empieza en 0: 0, 1, 2 y 3 son cuatro posiciones. 4 sería la quinta.
Por qué: La longitud dice cuántas hay, no cuál es la última etiqueta. Confundirlas es el error más caro del tema, porque a veces no salta a la vista: solo desaparece una lectura o se lee memoria que no es tuya.
Respuesta. Mezcla el cálculo con un efecto sobre el pin. Quien pide la media no puede evitar el LED.
Por qué: La descomposición exige que el subproblema no arrastre salidas que no son suyas. Si mañana la media va a un informe del bloque A, el pin no tiene nada que hacer ahí. Se compara fuera, en el si que ya conoces.
Respuesta. La media sale 640 en vez de 480. No debes escribir escribe 480 para taparlo.
Por qué: 640 es el síntoma de un recorrido mal contado, a menudo por saltarse el índice 0 y dividir por la longitud entera, o al revés.
1920 ÷ 4 = 480
1920 ÷ 3 = 640 Tapar la salida no corrige el para. Hay que ver qué i se han visitado.
En la vida real
Escribes y dibujas aquí mismo: no hay salto a otro módulo. La misma herramienta, a pantalla completa, está en l27-vectores-arrays-y-funciones.html y en el marco (útil si el navegador permite file:// en iframes).
Deja en el editor el vector de cuatro lecturas y una función media que devuelva 480 al ejecutar. En el cuaderno, escribe la tabla índice y valor. Añade, si quieres, una función que devuelva la primera lectura, lecturas[0], y explica por qué no es lecturas[1]. El pin, si lo nombras, se decide fuera de la función. Una buena entrega sigue dando 100 si cambias todas las casillas a 100.
reto_id: bach1-tic-L27