This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Vamos a mejorar un poquito nuestra lógica de programación y para eso vamos a hacer unas pequeñas pruebas de empresas Google, como Apple, como Uber y Space X o X o como le queráis decir.
Normalmente te dan un tiempo en el que lo hay que solucionar y hay que hacer lo que sea.
En este caso, lo que vamos a hacer nosotros es ir explicándolo, ¿vale?
Por eso uso Comic Code cuando programo.
Comic Code.
No la he hecho yo. Es un poco cara pero mola.
Ah, que cuesta dinero encima. No me digas que cuesta dinero Comic Code.
No me digas eso, que cuesta dinero. Comic Code y que pagas por ello.
Comic Code.
Es mentira, ¿verdad que utilizáis esto? No me lo creo.
¿De verdad utilizáis esto? No me lo puedo creer.
Lo bueno de CodeSignal, que es la plataforma que vamos a utilizar, es que es totalmente gratis, ¿vale?
O sea que vais aquí a Login, le vais a Developers Login y es una que se utiliza bastante en un montón de sitios.
Ahora además ha añadido como una inteligencia artificial que te ayuda con tus cositas y tal.
Fijaos que tenemos Arcade, tenemos Interview Practice, Challenges, Company Challenges, hay un montón.
Hay diferentes. En Interview Practice está bien porque aquí, por ejemplo, tenéis por temas.
Por ejemplo, en Arrays, aquí tenéis problemas, ¿veis? Este es el de Google, el de Amazon, Apple, Uber.
Hay de diferentes compañías y estos son problemas reales que muchas veces te lo ponen para filtrar, ¿vale?
Aquí LinkedIn, tenéis Facebook. Es que hay más. Porque estos son por temas, ¿vale? Que están interesantes.
Pero hay más que son estos, los Company Challenges. Los Company Challenges directamente ya te pone la empresa.
Por ejemplo, SpaceX lo tienes aquí y aquí tienes pues tres diferentes niveles y en cada nivel, pues esto se supone que debería tardar cinco minutos.
Se supone. Tampoco os tenéis que preocupar.
Hay que pagar por esos ejercicios. No hay que pagar. No hay que pagar. Yo nunca he pagado CodeSignal.
Entonces, ¿qué es lo que a veces se necesita? A veces necesitas, ¿veis? Créditos.
Estos créditos, ¿cómo se consiguen? Estos créditos, lo que se necesita hacer es el Arcade o el Arcade.
¿Cómo se quiere decir? Arcade. El Arcade, con el Arcade, cada vez que vosotros hacéis uno, os dan créditos.
Y conforme vais completando y más proyectos y más cosas, os van dando... Yo me quedé en el 13 y ya tengo un montón, pero un montón de créditos.
O sea, suficientes para avanzar. Con estos créditos es que podéis desbloquear algunos de los retos de compañías y tal.
Pero, ya os digo, no hace falta, no hace falta que paguéis. Yo no he pagado nunca jamás.
No sé si se ve... ¿Ves? Si tengo 59.000 créditos ya. Y nunca jamás he pagado.
No sé si en algún sitio se puede ver, pero ya os digo yo que no he pagado. Así que es totalmente gratis.
Vale. Entonces, entre todos los que se podrían hacer, yo he decidido cuatro porque creo que vamos de menos a más.
Vamos a empezar con uno que es sencillito y vamos a terminar con uno que es de un árbol binario.
Los de árboles binarios que sean mega difíciles, pero empiezan a ser un poquito más complicados.
Entonces, vamos de menos a más. Vamos a ir calentando con uno y empezamos con uno de Dropbox, que va a ser este de aquí.
Os voy esperando el chiste de patrocinar ColdSignals.
No me patrocina ColdSignals. Me encantaría que me patrocinase.
Así que si no os gusta Plataforma, está bien. Y si queréis utilizar otra, porque ahí tenéis HackerRank, HackerRank, por ejemplo.
Si me patrocinasen, no podría decir la competencia. Entonces, tenéis HackerRank, tenéis LeadCode. Hay un montón.
Pero una cosa que me gusta mucho de ColdSignal es que ya tiene los retos de las empresas ya preparados y está muy bien.
Otro muy típico, CodeWars. Hay un montón. Tenéis XersSims.org.
Y todos, todos los que os estoy diciendo son gratuitos.
Y el mejor, obviamente, que lo tenéis en español, el Adventist. Adventist en español, súper bonito.
Aquí lo tenéis. Tenéis 25 retos. Son navideños, pero están muy bonitos.
Vale, sí, todos son patrocinadores. Pues estos serían los más típicos, para que utilicéis el que queráis.
En este caso, vamos a utilizar CodeSignal. Vamos a empezar con este, pero ya os digo que mi idea es leerlo, entenderlo.
Entenderlo. Yo, intentar solucionarlo y luego darle las vueltas que hagan falta.
Porque igual falla, os explico cómo lo estoy pensando y lo que sea.
Vamos con el primero. El primero se llama Incorrect Passcode Attempts.
Y dice que tenemos un usuario muy importante, que le llaman View, con un documento muy confidencial.
Que está dentro de una cuenta de Dropbox.
Este usuario no quiere dejarle a nadie que pueda ver su documento importante.
Especialmente, sus compañeros de habitación, que muchas veces tienen acceso a sus dispositivos.
Abriendo la aplicación móvil de Dropbox, este usuario requiere un código de 4 dígitos.
Para asegurarse que la información sigue estando guardada confidencialmente,
el dispositivo se bloquea después de que se intentan 10 veces introducir un password.
Consecutivas. ¿Vale? Importante porque esto está en negrita por algo es.
Primer consejo. Si algo está en negrita, es porque seguramente hay que tenerlo bastante en cuenta.
¿Ok? Esto suele pasar mucho. Cuando te ponen algo en negrita, aquí hay jamón.
Dice, necesitamos implementar una función que dado un array de intentos que han hecho durante el día,
con el password correcto, que también nos ven aquí como parámetro,
va a chequear si el dispositivo debería bloquearse.
Por ejemplo, 10 o más fallos consecutivos se han hecho.
Y aquí nos ponen ejemplos.
Es súper importante también que nos fijemos en los ejemplos.
Normalmente en los ejemplos te pueden dar de 1 a 3.
No suelen dar más.
Si no dan ninguno, es una ratería.
Si te dan solo 1, es un poco rata también.
Normalmente te suelen dar 2.
Uno en el que es como el caso más obvio y otro en el que para que entiendas un poco la lógica.
Aquí, vamos a ver cuánto nos dan.
Nos dan 2.
Entonces dice, con el passcode 1, 1, 1, 1 y el array de intentos con todos estos, ¿vale?
El output debería ser true.
¿Por qué?
Porque se debería, claro, debe decir si se bloquea.
Y es que aquí es verdad que la primera vez lo pone bien,
pero luego tenemos 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.
Claro, ya ha puesto 10 veces mal el...
Bueno, esto sería de izquierda a derecha, que lo he contado de arriba a abajo,
pero es de izquierda a derecha.
O sea, sería 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.
¿Vale?
Entonces se ha puesto 10 veces mal, por lo tanto tendría que ser true.
Dice que el primer intento fue correcto,
claro, porque a lo mejor puede ser el mismo, el usuario,
pero luego se ha hecho 10 veces, se ha puesto incorrectamente,
se ha puesto 10 veces, por lo tanto debería ser true.
Ahora, aquí, si le pasamos 1, 2, 3, 4 y estos intentos,
tenemos 1, 2, 3, 4, 5, 6, 7.
Aquí se ha puesto bien, 1, 2, 3, 4.
Por lo tanto tendría que ser false.
Bueno, este es bastante sencillo.
Ya vemos que este es de los más fáciles,
pone que hay que hacerlo en 5 minutos.
En este caso, yo creo que un contador.
Vais a ver que muchas veces, aquí ya sabemos que tenemos que tener un contador
para asegurarnos que vamos a ir acumulando el número de veces que se ha puesto mal.
Así que aquí vamos a poner failed attempts y lo vamos a iniciar a 0.
Ahora, vamos a tener que hacer un bucle.
Muy típico, ¿no?
Si necesitamos, si tenemos un array, bucle.
Podéis intentar, yo os recomiendo una cosa,
que os enfoquéis primero a hacer las cosas, a hacer las cosas.
Entonces, consejos, lógica de programación.
Os voy a dejar primero los consejos y luego iremos explicando y degradando cada uno.
1.
O sea, lee y entiende bien el problema.
No os pongáis a programar sin antes haber entendido exactamente qué es lo que os están pidiendo.
Luego podéis fallar, no pasa nada, pero al menos de que penséis, vale, lo he entendido.
Si empezáis a programar sin haber entendido bien el problema, os vais a dar una hostia seguro.
Segundo, intenta hacer el caso más sencillo, vale.
Primero vamos a intentar hacer el caso más sencillo.
O sea, no intentéis solucionarlo todo de golpe.
Por ejemplo, aquí pone, vale, si los intentos son 0, vale.
Una cosa que podríamos pensar ya, mira, aquí no sé si se ve, a ver si os lo enseño,
pero aquí abajo hay un botón que pone run test.
Cuando ya le dais aquí, esto empieza a ejecutar los test.
Ahora mismo ya no me pasa ninguno, me dicen que todo es mal.
Si ya le ponemos return true, pues seguro me pasa alguno porque cuando pasas true o false,
pues es bastante binario y algunos, pues ves, van a ir pasando.
Pero es verdad que una cosa que podríamos pensar...
Ah, bueno, otra cosa importante.
Que normalmente aquí te dan más información que es bastante importante.
Y es que aquí, ojo, cuidado, también una cosa que tenéis que tener en cuenta son los constraints.
Esto también os lo suelen decir.
Por ejemplo, dice, el string va a tener, el del passcode va a tener 4 dígitos representando el passcode.
O sea, no perdáis tiempo haciendo checks que no tienen sentido.
Por ejemplo, si el passcode es el length del passcode o si es null, entonces false.
Es que esto no tiene sentido.
¿Por qué?
Ya te está diciendo que tienes que tener en cuenta que esto es así.
Porque no quieren que pierdas tiempo con estas cosas.
Vale, y lo mismo a lo mejor con el punto length, que sea mayor, si es menor a 4, pues entonces throw new error, no sé qué.
Esto si os lo explican y os lo piden, pues sí que podéis hacer.
Vale, y luego aquí dice que el array representa el passcode con el ta, ta, ta.
Y que los constraints es que el número de intentos siempre va a ser menor a 20.
Va a estar entre 0 y 20.
Y que los intentos, y que siempre va a tener un passcode y lo que devuelve siempre tiene que ser un booleano y tal.
Lo primero que vamos a tener que hacer, pues es contar los consecutivos que estén mal.
Vamos a poner let attempt of attempts.
Vamos a ir iterando.
Aquí lo podéis iterar como os dé la gana.
Yo recomiendo más un for porque así vamos a poder salir antes.
Si utilizáis un for each, utilizáis un find o utilizáis uno de estos, pues va a ser un poco más complicado.
Aunque podríamos utilizar el every, igual luego lo utilizamos.
Entonces vamos a utilizar el for.
Y aquí, pues nada, contamos si el intento, en este caso esto es un array de intentos, como podemos ver aquí en un test.
Vale, bueno, este es el vacío justamente.
Mira, pues este caso también sería interesante.
Ahora os explico.
¿Veis aquí que pone número de intentos?
Vale, pues aquí tenemos el número de intentos.
Pues si este intento, vamos a recuperar el primero, que sería este, el primer intento.
Si el primer intento es diferente al passcode, pues nada, vamos a seguir contando.
Fail attempts, le ponemos más, más.
Lo incrementamos en uno, ya tenemos el contador.
Pero si aquí ya, por lo que sea, el fail attempts es mayor o igual a 10, entonces devolvemos true.
Significa que se tiene que bloquear.
Ahora mismo no te preocupes tanto de la anidación de los if.
Es que se ve mal, no sé qué.
Ya tenemos tiempo de mejorar un poco el código.
Lo importante ahora es que funcione correctamente y haga lo que tiene que hacer.
Aquí el caso por defecto también, que aquí había puesto true antes, el caso por defecto tiene que ser false.
Porque aquí es en el único sitio donde vamos a tener que devolver true.
Si encontramos que tenemos más de 10 intentos fallidos, entonces devolvemos true.
Se tiene que bloquear.
Ya nos solucionaría algunos, pero no todos.
Si le doy el run test, seguramente algunos pasarán.
¿Ves?
Han pasado 9 de 11.
Pero no todos.
Pero bueno, ya estamos haciendo progreso de que al menos estamos mejorando y ya estamos pasando alguna cosa.
Todavía está mal porque no estamos teniendo en cuenta todos los problemas.
No nos asustemos.
Si en algún momento no nos pasan los tests, no pasa nada.
Lo bueno de los tests es que nos va a estar dando una pista.
Fijaos aquí que le estamos dando aquí la respuesta incorrecta.
¿Por qué?
Aquí pasa 1, 2, 3, 4, 5, 6, 7.
Aquí está bien.
1, 2, 3, 4.
Y en cambio aquí estamos devolviendo true cuando debería ser false.
¿Por qué está pasando esto?
Pues ya estamos viendo aquí un caso.
El caso de que pese aquí en el contador estamos contando 8, aparece aquí bien, pero no estamos reseteando el contador en ningún momento.
O sea, el problema es que no estamos reseteando el contador y aquí llega porque estamos incrementando constantemente.
O sea, necesitamos el caso de que, vale, ¿y qué pasa si el passcode sí que es el correcto?
Bueno, pues si es el correcto, vale, aquí alguien puede decir, pues hacemos un return false y ya está.
Pero no, porque aquí está el truquillo.
Esto también nos está fallando.
¿Por qué?
Porque no se ha dicho que es números consecutivos.
Y fijaos que ahora nos falla el test 1.
El test 1, fíjate que tenemos el passcode que sería este.
Claro, entra aquí, en este if no entra porque es el correcto, entra aquí y ya ha devuelto el false.
Pero está devolviendo false y debería devolver true.
¿Por qué?
Porque en realidad no tenemos que devolver si ha encontrado el correcto false.
Lo que tendríamos que hacer aquí sería reiniciar el contador.
De forma que, nos han dicho que son 10 fallos consecutivos.
Entramos aquí, ¿este está bien?
Vale, pues aquí reseteamos el contador.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 veces que estaba mal y luego aquí estaría bien.
Pero ya tenía 10 veces consecutivos porque el passcode era 11, o sea, era 1111.
Así que aquí lo que tenemos que hacer en lugar de hacer esto es que cada vez que encontremos la contraseña correcta, vamos a reiniciar el contador de los fallos.
Le he llamado fail attempts, pero esto tendría que ser consecutive fail attempts.
Así que esto lo pasamos aquí al 0.
Y con esto, vamos a ver si ahora...
Vale, pues ahora parece que estos test sí que no lo están haciendo bien, ¿vale?
Ahora sí que parece que los test estos están bien, pero ojo, cuidado, porque estos son como los test principales, ¿no?
Como los que te van a dar la pista de cómo funciona y todo esto.
Pero fijaos que hay muchos más test.
Para que ejecute todos los test tenéis que darle al submit este y ahora sí que pasará la batería entera de test, ¿ok?
Y ahora sí que ha funcionado correctamente.
Gracias por todo lo que haces por la comunidad.
Soy puertorriqueño viviendo en SF, trabajando en Silicon Valley.
Tengo 7 años en la industria.
Te sigo hace aproximadamente 6 meses y me has ayudado un montón en mi desarrollo.
Espero poder verte cuando vengas a SF.
A San Francisco y pueda firmarme el libro.
Puedo ser tu tour guide.
Pues mira, voy a ir a Silicon Valley justamente.
Así que nada, si nos vemos por ahí.
Mira, si me quieres ver, si alguien me quiere ver en San Francisco,
voy a estar en seguro, voy a ir a una quedada que va a hacer la gente de StackBlitz.
Y a ver, esta en San Francisco.
La hacen este lunes, si alguien me quiere ver.
Hay comida gratis, bebidas, va a haber charlas.
Y mira, hay todavía un montón de gente que va a ir.
Va a ir un montón de gente que conozco.
Va a estar Felipe, que le hicimos la entrevista aquí, que es un chico de OpenAI, desarrollador de OpenAI.
Va a estar Patak, que es desarrollador de Bit.
Va a estar también, ¿cómo se llamaba?
Leslie, Leslie de la GSConf.
Va a estar Pilipa de la GSConf también.
Así que si alguien desde San Francisco y quiere ir, pues creo que todavía hay la posibilidad de apuntarse.
Apúntate y me apuntas y ya está.
Gratis no, con mis impuestos.
Mis datos vendidos.
Joder, madre mía.
Con mis impuestos.
Está Miss pagando con tus impuestos las bebidas y tal.
Gonsi no sé si va a San Francisco.
No sé, no sé.
Pero bueno, que si queréis, el lunes voy a estar ahí.
Así que le podéis pasar y tal.
Entonces, ¿habéis entendido más o menos cómo hemos solucionado este problema un poquito paso a paso y tal?
Ahora le vamos a dar un poco una vuelta y os voy a explicar, lo voy a refactorizar un poco.
Podríamos hacer, este es el típico caso, que se podría hacer en una línea con un reduce.
Pero es una cosa que vamos a ver en algunos retos.
Hay retos que yo siempre recomiendo es, primero, aquí os lo dejo también como consejo.
Hazlo, hazlo bien y hazlo rápido.
Primero, haces la solución, la que sea, no importa.
No te preocupes primero en que sea entendible, en que funcione, que funcione, que funcione...
Que sea legible, que sea legible y que vaya rápido, ¿vale?
Estas serían como las tres, las tres que yo os diría, ¿vale?
No os preocupéis, esto es todo en el mundo de la promoción, pero que funcione, que sea legible y que vaya rápido, ¿vale?
Ahí serían las tres que yo os recomendaría.
Y tened cuidado porque hay veces que pensando que lo vais a hacer legible en una línea, vais a ver que seguramente va a ser más lento, ¿vale?
Vais a pensar, ostras, esto lo he dejado en una línea y tal, y va a ser más lento.
Entonces, tened cuidado con este tipo de cosas.
Por ejemplo, con reduce a veces puede ser peor porque es más lento que a lo mejor si lo haces con un for y tal.
Así que nada, solo que lo tengáis en cuenta.
En este caso, una optimización, porque una vez que lo he hecho, ya he estado pensando mientras lo hacía, ya está pensando, ostras, no me gusta este if con un if anidado, que esto queda súper raro, súper mal.
Esto yo lo podría simplificar.
Si le damos la vuelta, seguramente lo podríamos hacer mejor.
Es que si le damos la vuelta, se va a leer mejor.
Mirad, si yo esto, como lo tenía aquí, vamos a darle la vuelta y le decimos, oye, si el intento es el correcto, ¿vale?
El attempt es el correcto, entonces es que voy a hacer este reinicio del contador.
Aquí, pues, yo creo que se lee mucho mejor.
Y luego aquí podremos hacer el else if.
Podremos hacer dos cosas.
Una, para volaros la cabeza, que básicamente sería esto, ponerlo directamente aquí, ¿no?
El fail attempts, lo podríamos poner aquí y hacerlo aquí.
Lo podríamos hacer aquí y ya nos quitaríamos el código.
Y ahora os explico esto.
Retour True, ¿vale?
Y ya tendríamos todo esto, lo tendríamos simplemente así, ¿ok?
Y de hecho, lo podrías dejar un poquito más corto, pero al menos con esto, si no me he equivocado, si no he aliado parda, esto no debería funcionar exactamente igual.
¿Por qué hemos hecho esto?
A ver, esto lo podéis hacer así, lo podéis hacer de diferentes formas.
Pero esto lo que va a hacer es incrementar el valor de fail attempts antes de volver a utilizarlo.
Lo podéis hacer directamente aquí y entonces así podéis mirar ya y chequear el número de fallos y todo esto.
Otra cosa que podéis hacer realmente sería hacerlo después, lo podéis hacer aquí después, ¿vale?
Lo que pasa es que si hacéis esto, ¿vale?
¿Veis?
Ahora os falla, pero tendríais que hacer diferente el chequeo.
Lo podéis hacer así y así ya os va a funcionar perfectamente.
Y así os vais a evitar la anidación que teníamos aquí.
Una cosa que es muy interesante...
Ah, aquí no aparece.
Ah, pues es que hay en algunos que os aparece aquí una pestaña que se llama Solutions, que está bastante chulo para ver soluciones de la comunidad.
Y a partir de ahí os podéis volver locos y tal.
Bueno, os voy a dejar esta solución, pero os voy a retar a que lo intentéis determinar con un Reduce o que lo podáis intentar hacer con otro.
Se puede hacer, ya os digo yo que se podría hacer también con un Everi, se podría hacer con diferentes.
El Everi igual lo utilizamos en el siguiente, que creo que también se puede utilizar.
Lo podéis hacer con diferentes.
Y podéis probar en cada uno cuáles son sus ventajas y sus desventajas.
Pero antes de seguir, os voy a explicar un poco el tema de la complejidad algorítmica, ¿vale?
Un poquito para que lo entendáis y cómo funciona y todo esto.
Esa no me la sabía.
¿La del más más al principio?
Sí, claro, porque al final lo que podéis hacer es...
Si lo hacéis después, la diferencia es cuando se lee o cuando...
Claro, el fácil lo haces tú y nos dejas el chungo.
Pero si no es tan chungo.
O sea, el del Reduce, por ejemplo, es más fácil.
O sea, el de Reduce, si sabes cómo es el Reduce.
Se hace en una línea.
Tampoco es tan fácil.
Pero así, de hecho, estoy viendo que hay uno que lo ha hecho aquí.
Hay uno que te ha dejado la solución.
Y tampoco es tan difícil.
Sí, sí, ¿no?
Que vaga la peña del palo.
No, no, hazlo tú también, no sé qué.
Pero sí, es un momento, es un momento.
Hay que ver, ¿eh?
Bueno, vamos a hablar de la complejidad.
Primero, os voy a enseñar un recurso que os va a ayudar la vida para entender el tema de la complejidad.
Porque normalmente cuando tú terminas esto, os van a preguntar sobre la complejidad algorítmica o el Big O Notation y todo esto.
Este recurso os lo recomiendo mucho porque hay un montón de ejemplos de cada uno de ellos.
Os explica cuál es el positivo, cuál es el negativo.
¿Ves?
Aquí os dice esto.
No os preocupéis que ahora más o menos os voy a explicar cada uno de ellos y cuándo es interesante y cómo son los nuestros que hemos hecho.
Y de hecho, luego veremos otros más interesantes.
Pero el tema es, ¿la complejidad algorítmica para qué sirve?
¿Para qué estamos mirando la complejidad?
Básicamente es para saber que nuestras soluciones, para entender si nuestras soluciones son óptimas, ¿vale?
Si son eficientes, si realmente estamos utilizando correctamente el código para conseguir la mejor solución para solventar este algoritmo.
Y por lo tanto, optimizar los recursos que estamos utilizando.
¿Por qué?
Pues porque puede ser que en unos ejemplos muy pequeños, muy fáciles, oye, pues el algoritmo que hemos creado lo solucione bien, pero también tiene que ser escalable.
Y por lo tanto, imagínate que aquí en el ATEMS este, en lugar de 20 passwords, nos pasan 1.500.000, ¿vale?
Pues tenemos que entender si realmente nuestra solución va a escalar bien o se va a empezar, esto va a tardar muchísimo.
Si hay algún tipo de forma de hacerlo mejor todavía.
Entonces, tenemos diferentes notaciones para entender la complejidad de nuestros algoritmos.
Tenemos la de BICO, que es la más utilizada, pero no es la única, ¿vale?
Hay diferentes, está BICO, SmallO, hay diferentes, o sea, no me acuerdo, pero está la de OmegaO, la de...
Hay diferentes, no me acuerdo, es que como siempre se utiliza el BICO, los estudié en la universidad, no los he vuelto a utilizar en mi vida, solo, si nunca, los he utilizado el resto, solo el de BICO.
¿Por qué?
Porque el de BICO es como el caso peor, es como cuando, digamos, que tiende al infinito los parámetros que le llegan al algoritmo.
Y por lo tanto, como siempre se pone en el caso peor, va a ser el más idóneo para entender si nuestro algoritmo realmente está funcionando correctamente, si es óptimo o no es óptimo.
Entonces, ¿cómo funciona?
Lo que vamos a tener aquí es que vamos a entender cuál va a ser el coste, no solo en tiempo, sino también en espacio, y no te preocupes que ahora entenderemos un poco la diferencia entre los dos, en tiempo y en espacio de nuestras soluciones.
Por ejemplo, aquí tendríamos una solución que sería constante, que tendríamos que tiene el coste 1.
¿Por qué?
Porque esta función, independientemente de cómo lo tendríamos, siempre va a tener el mismo coste, y aquí tendríamos.
Cuando tú le pasas 20 elementos, 40, 60, 80, 100, no importa, porque vamos a tener que el tiempo es lineal.
Lo tenemos en lineal, no, que sería constante en 1, no importa cómo lo estamos pasando, que este es el mejor, porque no importa cuánto le pasemos, que no va a tener ningún crecimiento, se va a quedar exactamente ahí.
Luego tendríamos el crecimiento lineal, que sería el de la n, que conforme van creciendo el número de elementos, va creciendo exactamente igual el tiempo.
Hablamos de tiempo, pero claro, no hablamos de segundos, hablamos como de tiempo, de cómo escala el tiempo.
Pero tened en cuenta que no tiene sentido hablar de segundos, porque dependiendo de dónde vas a ejecutar este algoritmo,
si lo ejecutas en un ordenador buenísimo, o si lo ejecutas en un ordenador muy antiguo, el tiempo en segundos va a ser diferente.
Por lo tanto, estamos hablando de tiempo como unidades de tiempo, de cómo es que escala conforme va creciendo el número de elementos que va a recibir nuestro algoritmo.
Y no solo pensáis muchas veces como número de elementos como si fuese un array, porque hay que tener en cuenta muchas veces también que no es que el algoritmo siempre reciba un array,
porque puede ser que hagas una multiplicación, un número, y con el 1 pues tarde 1, con el 2 tarde 2, con el 10 tarde 10, también puede ser un número, pueden ser diferentes cosas.
Es la entrada de nuestro algoritmo, que no siempre tiene por qué sonar un array.
¿Veis? Y aquí podemos ver, por ejemplo, cómo sería el crecimiento con una notación de n.
Estamos viendo aquí que cada vez que va aumentando cada uno de los elementos o parámetros que entran a nuestro algoritmo, pues tiene este crecimiento.
Y esto pues iríamos viendo, cada uno, aquí tenemos un crecimiento que es n elevado a 2, pero este no es el peor, hay diferentes.
Aquí tenemos, por ejemplo, la comparativa. Ya podemos ver que el de coste 1 es el más óptimo, pero hay muchos peores.
No, hay un montón. De hecho, aquí tenemos una tabla que está bastante interesante.
Hay algunos un poco especiales, como por ejemplo el de logaritmo de n, porque el de logaritmo de n, como los arrays, o bueno, los arrays, o lo que sea,
lo que podemos hacer es ir dividiendo la carga de trabajo cada vez que lo hacemos.
No es que crezca de forma lineal según el número de parámetros, sino que va creciendo el número de parámetros, pero el crecimiento no es lineal.
Esta tabla está muy chula porque fijaos que aquí tenéis que es constante, el logarítmico es el que os digo yo,
os dice en la descripción cuáles son los mejores, obviamente el constante, el que independientemente del número de elementos que le pases
siempre tiene el mismo coste en tiempo, pues es el mejor.
El logarítmico es el que, conforme tú le vas pasando más elementos, tiene un crecimiento, pero el crecimiento está dividido.
O sea, por ejemplo, si tú le pasas 100 elementos, su coste es 5. Si le pasas 1000, su coste es 7.
Ha crecido, pero no está creciendo a la misma velocidad, digamos, que el número de elementos que le estás pasando.
Luego tenemos el lineal, el lineal logarítmico, el cuadrático, el cúbico, el exponencial y el factorial.
El factorial es el peor, es el que básicamente te va a tardar 10.000 millones de años sin hacer cualquier tipo de cosa.
Y aquí tendríamos un poco esta idea de hacer la computación de 10 cosas el coste que tiene y el de hacerlo con 100 cosas el coste que tiene.
Y veríamos aquí cómo es el crecimiento. Por ejemplo, el lineal, hacer 10 cosas tarda 10 veces y hacer 100 cosas tarda 100 veces.
Y el constante tendríamos 1 y 1. El logarítmico tendríamos que tarda 3 y que tarda 7.
Tiene un crecimiento, pero no es al mismo ritmo que el número de cosas que hace.
Y aquí tendríamos el diferente. El factorial es el peor, que ya os digo yo que este es el que hay que evitar a toda costa.
Dicho esto, un poquito, si os gusta el tema del beacon notation, igual un día podemos hacer un curso desde cero bien hecho.
Pero básicamente quiero que entendáis un poco la idea porque seguramente os van a preguntar esto.
Y es interesante que al menos tengáis un poco unas nociones básicas.
Es muy fácil muchas veces de entenderlo. Hay veces sí que puede ser un poco más complejo.
Pero por ejemplo, en este, ¿cómo es la complejidad? Tanto temporal como espacial.
Porque hay la complejidad temporal, que es el tiempo, el tiempo que va a tardar nuestra solución del algoritmo.
Y la espacial, que es cuánta memoria tenemos que utilizar con nuestro algoritmo.
Entonces, vamos con la temporal.
En este caso, la temporal es la cantidad de tiempo que va a tomar este algoritmo en ejecutarse según el tamaño de entrada.
En este caso, va a ser lineal.
En este caso, sería on.
¿Por qué es on?
Bueno, pues porque la función itera cada elemento del arreglo a temps.
Entonces, si a temps es 10, ¿cuántas veces itera?
Pues 10 veces.
Si es 100, ¿cuántas veces itera?
Pues 100 veces.
Si es 1000, o sea que ya estás viendo exactamente cómo funciona.
Ojo, cuidado con esto.
Estamos siempre poniéndonos en el caso peor.
¿Por qué?
Porque alguien puede decir, ya, pero es que en el mejor de los casos puede ser que no itere 100 veces, ¿no?
Que me pongan 100 intentos y resulta que las 10 primeras ya entramos aquí y le damos un return true y solo lo ha iterado 10 veces.
O sea, me ha venido aquí un array de 100 veces, pero como ya hemos terminado aquí, lo hemos hecho 100.
Por eso os digo que hay diferentes notaciones.
Entonces, el BCO, la idea sería básicamente que nos ponemos en el caso peor.
¿Por qué en el caso peor?
Porque tenemos que estar preparados ante la fatalidad.
Y en este caso tenemos que mirar que nuestro algoritmo, en el peor de los casos, tiene este coste temporal.
¿Vale?
Así que piénsalo bien.
No siempre te quedes, no, pero en el mejor de los casos puede pasar esto.
No.
Tienes que ponerte en el peor de los casos.
Ya os digo que hay otras notaciones que sí que miran el mejor de los casos, la media de los casos.
Hay diferentes, pero no se suelen utilizar.
Siempre se utiliza el más pesimista.
Porque, claro, lo que queremos que nuestros algoritmos siempre en el peor de los casos funcione bien.
Así que, como estamos iterando el array, pues ya podéis ver que lo tenemos que hacer para cada uno de los elementos.
Ahora, el espacial, la complejidad espacial, podríamos entender que es como la cantidad de memoria que requiere el algoritmo
para que pueda ejecutar su proceso, que funcione correctamente, según el tamaño de entrada.
¿Y qué memoria estamos utilizando aquí, que estamos guardando y tal?
Lo único que estamos utilizando aquí es esta variable, donde estamos guardando en memoria esta variable.
¿Y qué coste tiene esto?
O sea, si el array de attempts tiene 10.000 millones de elementos, ¿cuánta memoria estamos utilizando?
¿Cuántos espacios estamos utilizando?
Piénsalo así.
Estamos utilizando uno.
No importa cómo de grande, pequeño, mediano, inmenso sea el array de attempts, porque siempre vamos a estar guardando un valor.
Vamos a ver después que hay otros casos en los que puede ser esto más complejo, porque puede, por ejemplo, guardar un array según el número de elementos.
Imagínate que según el número de elementos estemos guardando solo un tercio del array.
Entonces ya sí que podríamos ver que podríamos tener un logaritmo n.
O que estamos guardando un array mapeado.
Pues ya sería n, porque el n número de elementos lo estamos guardando en el array, porque por cada elemento guardamos otro elemento.
Así que en este caso va a ser constante, independientemente de la entrada, el espacial, vamos a decir, este sería espacial, ¿vale?
No especial, espacial.
Y este sería el temporal, ¿vale?
El temporal o, sí, vamos a llamarle el temporal.
Espacial o uno, ¿vale?
Va a ser constante.
Temporal lineal o n.
Ok, hasta aquí bien.
El let attempt cuenta.
Este, en realidad, este no contaría.
Podríamos contarlo, pero también sería constante.
O sea, si es constante sería exactamente lo mismo.
Pero en este caso tenemos que tener en cuenta que en realidad ya esta memoria está asignada y lo único que estamos haciendo es reutilizarla, ¿sabes?
O sea, que no sería como que estamos guardando y tal, sino que ya está este array aquí.
Podríamos utilizarlo directamente así y sería un poquito exactamente lo mismo.
Así que en este caso yo no lo contaría.
Es parte de la sintaxis del bucle.
Claro, que es parte de la sintaxis y en realidad ya está en memoria eso y yo entendería que no sería lo mismo.
O sea, y además sería constante porque no estaríamos guardando.
Sería reutilizar el mismo, así que también sería constante.
Me too, es por eso que con los ejercicios de avengers tenía muchas variables.
Esto te tiraba un menor puntuaje.
No exactamente, pero tal.
¿Por qué no es for const attempt?
Porque esto, bueno, lo podemos hacer, ¿eh?
Puedes hacer esto sin ningún problema.
Era porque era un poquito más corto, ¿eh?
Pero no funcionaría, no habría ningún problema utilizar el const porque justamente no lo estamos haciendo.
Y ya está.
Entonces, este sería el primero.
Hemos visto complejidad.
Vamos a hacer otro y vamos mirando también la complejidad.
Lo vamos comentando y todo esto.
Vamos a hacer el de SpaceX.
Este ya empieza a ser un pelín más complicado.
Un pelín, un pelín.
Pero vamos ya encrechendo y así vamos mejorando.
Un saludo desde Chile.
Hola.
En mi empresa quieren cambiar de Netcore a Volant como framework de backend.
¿Qué opinas?
¿Tienes algún curso?
No tengo ningún curso, pero me parece, a ver, me parece polémico, pero me parece bien.
O sea, entiendo que han tomado esa decisión por algo.
Así que no tengo ningún curso, pero me parece bien.
Algo habrán hecho, algo habrán visto, ¿no?
Que estará bien.
Vamos con el segundo.
Este es de SpaceX.
Tenemos aquí tres también.
Ya os digo que si os gusta, pues podemos hacer el de Medium.
El de CPU Emulator.
Este está muy chulo.
Este es muy divertido.
Son 30 minutos porque es bastante largo.
Este no lo vamos a hacer hoy porque hay que hacer unas cuantas cosas y es bastante largo.
Pero está muy chulo porque es un compilador y tiene bastante cosita.
Y te dan 2000 puntos y lo terminas.
No, vamos a hacer este.
Vale, este también está interesante.
Es sencillo.
Es similar al que hemos hecho.
Pero tiene ya un poco más de complejidad porque ya tenemos que utilizar un diccionario o un hashtable para guardar cositas.
La secuencia de lanzamiento maestro consiste en una secuencia independiente de pasos para diferentes sistemas.
Tu objetivo es verificar que todos los sistemas individuales están estrictamente en un orden creciente.
¿Vale?
Orden creciente.
En otras palabras, para dos elementos, i y j, vale, i siempre menor que j, de la secuencia de lanzamiento maestra, que son del mismo sistema, teniendo que system names i es igual a system names j, sus valores tienen que estar estrictamente en un orden creciente.
Vale, para entender esto, porque creo que es un poco complicado, esto es una cosa que también con los algoritmos es un poco jodido, de que hay que entender muy bien a qué te refieres y tal.
Vamos a ver el ejemplo.
Por ejemplo, tenemos system names.
Aquí tenemos stage 1, stage 2, dragón, stage 1, stage 2, dragón.
Entonces ya vemos que se repiten los system names.
Entonces lo que nos quiere decir es que stage 1, este, va con el step numbers del mismo índice.
O sea, stage 1, este sería con 1.
El stage 2 iría con 10.
El dragón iría con el 11.
Y este stage 1 que vuelve a aparecer aquí iría con el 2.
Y aquí lo que tenemos que comprobar es que previamente este stage 1 tenía 1, o sea que era, es creciente,
el anterior era más pequeño que el actual, o sea que hasta ahora, bien.
El stage 2 es 12.
Tenemos que revisar, el anterior de stage 2 era 10, por lo tanto sigue con su creciente, ¿no?
Pues perfecto.
Y dragón va con el 111.
El anterior de dragón era 11.
Así que también vemos que va creciente, por lo tanto debería ser true.
En este caso funciona correctamente.
Ahora vamos a ver.
Ah, bueno, nos lo está explicando.
Vale, está bien.
Luego aquí tenemos system names.
Vale, tenemos stage 1, stage 1, stage 2, dragón.
Aquí vemos que el stage 1 empieza en 2 y el siguiente stage 1 pasa al 1.
Por lo tanto ya no sigue la confirmación de que sea creciente porque ha pasado del 2 al 1.
Así que aquí es false.
Tiene que ser false.
No tiene sentido seguir mirando porque total ya sabemos que es false.
Y esto está bien porque como no tengo que seguir mirando, pues aquí podemos utilizar el every.
Lo que vamos a hacer con every es revisar que todos los elementos de un array pasen una condición.
Vale, vamos a ver.
¿Cómo podemos hacer esto?
Está claro que vamos a tener que ir guardando cuál es el contador anterior.
Como lo hemos hecho, ves que yo aquí he estado haciendo stage 1.
¿Qué tiene?
Stage 1, ¿cuánto tiene?
Vale, pues lo primero que vamos a hacer aquí es poner start.
Vamos a crear un objeto, seguramente luego lo vamos a hacer con otra cosa, pero vamos a tener que guardar, por ejemplo, pues el stage 1 empezó en 1.
Luego tendremos el stage 2, no sé qué.
Esto lo vamos a hacer de forma dinámica, obviamente, pero necesitamos guardarlo en algún sitio.
Luego vamos a tener que iterar cada uno de los system names.
Para iterarlo vamos a utilizar justamente, vamos a ver aquí system names y vamos a poner every, ¿vale?
Para revisar cada uno de los elementos y para cada sistema, ¿vale?
No sé si se llama el system name.
Cada sistema vamos a recuperar también el índice, que nos lo pasa aquí como segundo parámetro.
Vale, para cada sistema vamos a revisar antes si lo teníamos guardado, porque tenemos que mirar si lo teníamos guardado previamente, ¿no?
O sea que vamos a recuperar el previous system, stored system, ¿vale?
Vamos a tener, bueno, previous system no, previous count, previous counter, ¿vale?
Así recuperamos el número.
Por ejemplo, si esta sería la segunda iteración, ya vamos a, imagínate que ya estamos aquí, pues vamos a mirar si ya estaba previamente, ¿no?
Y miramos si estaba el contador previamente.
Y vamos a recuperar cuál sería el actual, ¿no?
Actual counter.
Y esto lo sacamos del step numbers del index.
O sea, en la primera iteración, por ejemplo, primera iteración sería, imaginamos que tenemos este ejemplo de aquí, ¿vale?
La primera iteración tendríamos que system sea stage 1 y que el index, vamos a poner system, y que el index sería 0.
Bueno, entonces, aquí, pues, esto sería undefined, porque no lo tendríamos, ¿ok?
Y aquí tendríamos, en este caso, tendríamos 1.
Esta es la primera iteración, ¿no?
Si es undefined aquí, esto lo tenemos que revisar.
Tenemos que mirar y asegurarnos que realmente, si es undefined, que funcione correctamente.
O sea, que no le podemos poner un valor por defecto, porque si nos ponemos a mirar aquí las constraints, ¿vale?
Las constraints dice que es un array de números positivos, ¿vale?
Un array de números positivos.
Mira, esto es interesante porque si nos dice que es un array de números positivos,
significa que aquí, en lugar de trabajar con el undefined, podríamos utilizar un valor por defecto inicial
que fuese el 0, porque si son positivos, si esto es undefined, pues, podemos tener el 0
y así siempre compararemos a través del 0.
Así, como puede ser el siguiente, como mínimo tiene que ser 1, o el 2, o el 3, o el 4, o lo que sea,
así empezamos desde 0 y así vamos comparando, ¿vale?
Pues, vamos a quitar esto, vamos a quitar esto, y ya solo tenemos que hacer el if.
Y así no tenemos que hacer si typo, undefined y tal.
Lo único que tenemos que hacer es, si el previousCounter es mayor o igual al actualCounter,
pues, devolvemos false.
Porque esto significa que el contador anterior es mayor y, por lo tanto, ya no es creciente,
sino que sería decreciente.
Este sería el caso que tenemos aquí, ¿no?
Si aquí stage1 empieza en 2 y el siguiente stage1 es 1,
entraría en esta condición y ya devolveríamos que es false.
Ahora, si este no es el caso, lo que deberíamos hacer es,
en stored vamos a guardar la siguiente, en este caso, en storedSystem,
y guardamos aquí el actualCounter, porque nos va a servir para la siguiente iteración,
y devolveríamos true.
Y con esto ya lo tendríamos, si lo hemos hecho todo bien.
¿Sí?
Lo tenéis más o menos, que os voy a preguntar.
Si no, lo explico otra vez, ¿eh?
ActualCurrent.
Ah, es verdad que he puesto actual y tienes toda razón,
que actual no significa current.
CurrentCounter.
Gracias.
Perdón, humanuba.
Tienes razón.
Dicen estrictamente crecientes.
Bueno, pero eso vamos a mirar.
Vamos a hacerlo estrictamente crecientes.
Vamos a...
Otra vez, otra vez.
Lo explico otra vez.
Vale, lo explico otra vez.
Aquí en SystemNames nos llega el array que tenemos aquí de todos los nombres.
Aquí en SteepNumbers, todos los números.
¿Vale?
Entonces, lo que vamos a hacer en SystemNames,
utilizamos el método every.
Lo que hacemos con el método every es que every,
si devuelves false, significa que vas a devolver false.
¿Vale?
Si aquí hay alguna condición aquí, alguna de estas condiciones.
Mira, es que a lo mejor para el every,
lo mejor es que os lo enseñe en un ejemplo aparte,
que os va a costar menos.
Y así vais a entender el every seguro, ¿vale?
Porque si no...
Mira, vamos a poner aquí...
Bueno, Numbers.
Vamos a poner 1, 2, 3.
¿Vale?
Numbers every return n es mayor que 0.
¿Vale?
Entonces, ¿cómo funciona el every?
Lo que funciona es, tú tienes un array de números, ¿vale?
El 1, el 2 y el 3.
Every tenemos diferentes métodos de array.
Tenemos forEach, tenemos el map, tenemos reduce, tenemos some,
tenemos...
Es que tenemos un montón.
El find, el filter...
Hay un montón, ¿vale?
Entonces, ¿para qué sirve el every?
El every lo que sirve es, para hacerse la pregunta,
¿todos los elementos del array cumplen la condición?
Esa sería la pregunta que viene a responder.
Y es que aquí lo que estamos preguntando es,
oye, ¿todos los elementos del array cumplen la condición?
¿Qué condición?
Esta condición, ¿vale?
Esta sería la condición.
De hecho, la puedes poner aquí.
Function, condition...
Lo puedes hacer así, para entenderlo mejor.
¿Vale?
Lo podemos hacer así y ya está.
Entonces, esta sería la condición que le pasamos.
Por lo tanto, lo que estamos aquí explicando es,
oye, la condición esta es saber si cada elemento del array es mayor a 0.
¿El 1 es mayor a 0?
Sí.
¿El 2 es mayor a 0?
Sí.
¿El 3 es mayor a 0?
Sí.
Por lo tanto, ¿todos los números cumplen esta condición?
Sí.
¿Vale?
Ahora, si le decimos que sea mayor a 5,
¿todos los números cumplen esta condición?
No.
Porque, obviamente, el 1 es menor.
Lo interesante que tiene el every,
que esto sí que es importante,
es que hay que saber que va a salir del bucle
en cuanto encuentre una condición que no cumple.
¿Y esto cómo lo podemos saber?
Lo podemos saber porque si ponemos un console.log de n,
fijaos que solo aparece el 1.
¿Esto qué hay que decir?
Que en la primera iteración,
en cuanto ha llegado aquí el 1,
ya ha encontrado que esto era false,
ha devuelto el false,
y ha dejado de chequear las siguientes condiciones,
porque no tiene sentido.
Como tienen que todos cumplir la condición,
con que 1 ya no cumpla la condición,
ya sale del bucle.
Por eso puede ser mucho más óptimo
que, por ejemplo, utilizar un for,
utilizar un for no,
utilizar un for each,
o utilizar un filter, ¿vale?
Puede ser mucha mejor opción.
El filter, por ejemplo, los filtraría todos.
Fíjate la diferencia.
El filter va a filtrar todos los elementos
que pasan esta condición,
pero, como puedes ver,
está iterando todos los elementos.
¿Por qué?
Los está iterando de forma innecesaria,
porque nosotros lo que queremos en realidad
es que pare en cuanto tengamos...
Bueno, ahora sí que lo está iterando de forma necesaria.
Bueno, innecesaria también.
Pero bueno, ¿veis?
Aquí sí que los está iterando todos,
porque el filter tiene que filtrar todos los elementos.
Pero el every,
como estamos preguntando
si todos los elementos de la array
cumplen la condición,
con que haya uno que no lo cumpla,
pues ya va a salir.
Y por eso es mucho más interesante
y muchas veces es mucho más óptimo
que utilizar otras alternativas.
En este caso, imagínate que sea mayor que 0.
No, que 0 no.
Que 2 o no.
Que 1.
Que 1...
Es que si pongo que 1...
Claro, si le pongo mayor que...
Algo así, ¿no?
Claro.
Por ejemplo,
si le ponemos que sea mayor que 1
y empezamos con el 4,
el 4 sí que es mayor que 1,
por ejemplo, ese sí lo itera.
Y cuando llega el siguiente,
como este no cumple,
entonces parará ahí
la iteración del bucle.
Ya no mirará el siguiente
porque ya con que 1 falle.
Y aquí ya si le ponemos
que sea mayor a menos 1,
ahora sí que pasará a todos
y nos devolverá true.
O sea,
que lo interesante de todo esto
es que el every nos responde.
Todos los elementos del array
cumplen la condición
que le estamos poniendo.
Volvemos a nuestro código.
Entonces,
por eso estamos utilizando el every.
Le estamos haciendo pregunta aquí.
¿Todos los elementos
del array
cumplen
la condición
que
su contador
es creciente?
¿Vale?
Así lo estamos haciendo.
Esto es lo que queremos responder.
La condición que tenemos
es saber si todos los elementos
del array
cumplen esta condición.
Ahora,
¿cómo lo estamos haciendo?
Pues lo que estamos haciendo
es guardar
en un diccionario,
aquí vamos guardando
cuál era el contador anterior
porque necesitamos comparar.
Así que,
por ejemplo,
si tenemos el stage 1,
el stage 1 aquí,
la primera vez que entra
no tenemos con qué comparar
porque es la primera vez
que aparece.
¿Ves?
Aparece aquí el 1.
No tenemos un contador previo
y por eso es que hacemos esto.
Vamos a mirar primero
si lo habíamos guardado
y si no lo hemos guardado
le ponemos que el valor
por defecto
sea 0.
Luego,
lo que vamos a hacer
es tener el contador actual.
O sea,
tenemos el previo
que por defecto
sea 0
si no lo habíamos guardado
y el actual,
que el actual
sería el número este,
el 1.
¿Vale?
Entonces,
ahora lo único
que tenemos que saber es,
oye,
¿el número anterior
era menor
o era mayor?
Porque claro,
si el anterior
era menor,
perfecto,
pero si era mayor,
ya lo hemos roto.
Si es menor,
es que estamos haciendo
correctamente la subida.
Y una cosa importante
es que tenemos que comparar
exactamente
con el nombre del sistema.
Aquí tenemos el stage 1,
¿vale?
Y por eso estamos utilizando
aquí este system,
voy a poner system,
system,
name,
¿vale?
Para que lo veáis más claro.
Para que esto veamos
paso a paso,
podemos ponerlo aquí
y podemos traernos,
podemos traernos
esto de aquí.
Y fijaos,
tú, tú, tú,
vamos a poner esto por aquí,
const,
vamos a poner esto por aquí,
tú, tú, tú, tú, tú,
const,
¿vale?
Y,
bueno,
esto con un debugger
molaría mucho más,
pero bueno,
vamos a poner con la consola
y ya está,
console.log,
previous counter,
current counter,
y vamos a poner
el system name,
¿vale?
Y así lo tenemos,
lo tenemos fino.
Y ya ejecutamos aquí
el solution
con el system names
y el
step numbers,
step numbers,
¿vale?
Y ya,
bueno,
que todavía no sé
si la solución es correcta,
pero bueno,
aquí podemos ver
todas las iteraciones.
Para el system names,
¿cuál era el previous counter?
Era 0
y el current counter
es 1,
¿vale?
Fíjate,
empezamos aquí.
Siguiente iteración,
vamos a stage 2,
previous counter
todavía no teníamos ninguno,
current counter
era 10,
es este,
¿vale?
Dragón,
por lo mismo,
el 11,
entonces no teníamos
previous counter,
pero aquí en el stage 1,
ahora sí,
cuando aparece aquí
en esta iteración,
el previous counter
era este,
este 1
que hemos guardado
previamente,
por eso lo tenemos
que guardar aquí
en este objeto,
y lo tenemos que guardar
exactamente
con el sistema,
el número,
el nombre del sistema,
para tener
un diccionario
completo
en el que nos va
a poder decir,
oye,
este sistema
tenía este número,
este otro sistema
tenía tal,
este store,
para que te hagas una idea
como sería,
este store tendría
una forma tal que así,
stage 1,
bueno,
sería algo así,
stage 1,
sería 1,
stage 2,
sería 10,
este,
el dragón,
sería 11,
y así es como se vería
más o menos,
entonces vamos a ir
accediendo en cada uno
de los números previos
y ya está,
¿vale?
Así lo tendríamos,
printe a store,
¿vale?
printeo el store
para que veáis
cómo está el store
en cada paso,
¿vale?
Mira,
primero el store
está vacío,
la primera iteración,
luego la siguiente iteración,
en el store,
ya hemos guardado
el stage 1 anterior,
¿vale?
Porque aquí
habíamos visto
el sistema 1
del stage 1,
¿vale?
Pues lo hemos guardado,
en la siguiente iteración
hemos guardado
stage 2 con el 10,
¿ves?
que es este anterior,
en el siguiente,
aquí tenemos el dragón,
y aquí es donde ya viene
lo interesante,
aquí en esta iteración
que estamos mirando
el stage,
no,
perdón,
en esta iteración
que estamos mirando
el stage 1,
ahora sí que el stage 1
es la segunda vez
que sale
y ahora sí que estamos
comparando el previous
con el current,
con el actual
y ya está,
así lo vamos obteniendo
y ya está
y ahora sí que podemos mirar
que nos está pasando
a true.
Vamos a mirar
si esto nos está dando bien,
¿vale?
Si realmente esto
nos está pasando
y...
vale,
esto es correcto,
me lo podía imaginar
totalmente.
¿Dónde defines
cómo se guarda en store?
Lo tenemos aquí,
lo tenemos justamente aquí,
estamos poniendo aquí
store,
aquí imagínate
que si system name
es igual
a stage 1,
esto significa
que esto sería
store,
stage 1
y aquí estaríamos
guardando el current counter
que en la primera iteración
sería 1,
o sea,
imagínate
que esto sería así,
lo estamos guardando aquí,
¿vale?
justamente antes
de devolver el true,
o sea,
decimos exactamente
que no entendí
el requerimiento,
pero hombre,
a ver,
¿cómo no va a entender
el requerimiento?
A ver,
vamos a ver,
os voy a hacer un croquis ya,
o sea,
os voy a hacer el croquis
porque es que
no me puedo creer,
no me lo puedo creer,
vamos a ver,
vamos a ver,
vamos a ver,
vamos a ponernos un croquis,
estos son los system names,
voy a haceros el croquis
porque esto es que
lo tenéis que entender,
system names,
¿vale?
lo tenéis que entender
porque esto es clave,
porque luego no entráis,
space x,
por mi culpa
y me voy a sentir culpable,
tío,
me voy a sentir muy mal,
entonces,
vamos a poner el step numbers,
¿vale?
lo que dice esto es,
te dan el system names
y te dan los step numbers,
y lo que te está diciendo
es que cada nombre de sistema
tiene que tener
sus pasos
de forma creciente,
¿qué quiere decir?
que system names,
este tendría,
mira,
voy a poner esto aquí
para poder hacer la relación mejor,
¿vale?
tenemos esto separado,
lo que te está diciendo es que
el stage 1
va con este
y este
va con
el suyo,
2,
3,
4,
1,
2,
3,
4,
¿vale?
ahora,
el stage 2,
vamos a ponerlo con otro,
va con este
y este stage 2
va con
1,
2,
3,
4,
5,
1,
2,
3,
4,
5,
con este
y luego tendríamos dragón,
ay,
perdón,
tendríamos dragón,
¿vale?
que es este
y
este dragón
que va con este,
con este 111.
¿qué es lo que está diciendo esto?
lo que nos está diciendo es que
cada vez que miremos stage 1
tenemos que mirar su step number,
¿vale?
y compararlo con el anterior,
la primera vez que sale stage 1
no tenemos anterior,
vale,
pues nada,
no hay ningún problema,
la siguiente vez que aparezca stage 1
que es este,
tenemos que mirar su step number
y aquí lo que tenemos que hacer
es comparar
que
el anterior
que es 1
sea menor
que el actual
que es 2
porque nos está diciendo
que esto es como
son los lanzamientos
de cohetes
de SpaceX
en los que tiene que ser
incremental
cada uno de los pasos
de cada uno de los sistemas,
¿vale?
Entonces,
para stage 1
tenemos que mirar
su posición esta
es el 1
y stage 1 aquí
es 2
en este caso stage 1
siempre es incremental
ahora stage 2
su paso es 10
la próxima vez que sale
stage 2
su paso es 12
es incremental
dragón es 11
y dragón 111
es incremental
ahora imagínate
que por lo que sea
aparece
que stage 1
aquí
es 5
pues ya no es incremental
¿por qué?
porque stage 1
empiezan 5
pero cuando vuelva a aparecer
stage 1
es 2
esto significa
que no es incremental
sino que el número
es decremental
va hacia abajo
y por lo tanto
ya sería false
ya está
con un map
estructura de datos
saldría con los system names
totalmente
podríamos utilizar
un map
sin ningún problema
y eso es lo que nos están
lo que nos están pintando
¿vale?
entonces
aunque funciona
lo que no creo que es todo correcto
es el uso del every
ya que la función que se pasa
como callback
es mutable
muta el store
creo que es mojar
usar directamente un for off
de la misma forma
que el anterior ejercicio
pero eso que dices
pumuki
tampoco tiene mucho sentido
porque si utilizas un for off
por un lado
el que el callback
es mutable
eso no es así
el callback no es mutable
lo que dices tú
que entiendes
que es mutable
es esto
pero
uno
que algo sea mutable
no lo hace incorrecto
¿vale?
un error muy común
que lo veo muchas veces
es el hecho
que la gente ve
lo mutable
como algo negativo
algo que sea mutable
no pasa absolutamente nada
ahora
si quieres hacer
programación funcional
100%
pues seguramente
te interesará más
hacer otro tipo de cosas
podrías hacerlo
con reviews también
pero yo creo que
es innecesario
no pasa nada
con mutar un objeto
es bastante típico
realmente
tener objetos
o arrays
que muten
es normal
no es algo negativo
no es algo malo
entonces
dejad de
poneros
que siempre
con que mutar algo
es negativo
luego
el callback del every
no es mutable
y de hecho
para la solución
del for off
vas a necesitar
también
tener un diccionario
donde vas a tener
que estar guardando esto
entonces
si lo intentas
haz la solución
del for off
y vas a ver
que vas a tener
el mismo problema
así que no
no te dan ningún problema
yo solo no entendí
si esa parte
donde se guarda el store
lo manda como formato objeto
no
porque esto ya es un objeto
y en los objetos
para guardar algo
utilizas esta anotación
y ahí guardas el counter
y ya está
entonces
también se puede hacer
con un reduce
claro
podrías hacer el reduce
que el acumulador
sea el store
y así sería
más programación funcional
¿cuál es el problema?
si lo haces 100%
con programación funcional
en el reduce
sería mucho peor
en cuanto a rendimiento
de hecho esto
ya se sabe
¿por qué?
porque si tú lo que haces
es crear un nuevo objeto
en cada iteración
obviamente eso va a tener
mucho más coste
que el hecho de mutar
directamente el objeto
sobre esto
os voy a recordar
os voy a recomendar
un
un vídeo muy chulo
que es de gente de Google
don't use reduce
a ver si lo encuentro
que está mucho
esto
el reduce bad
este vídeo está muy chulo
os lo recomiendo un montón
porque son dos ingenieros
de Google
que están hablando
sobre el reduce
y hablan cuando
oye
tiene sentido utilizar reduce
está bien
no pasa nada
pero también habla
de cuando no utilizarlo
pues hay algunos
que tienen sentido
otros que no tanto
y habla de
de justo lo que os he comentado
por ejemplo este
este es un ejemplo
muy típico
de que por hacer
un programación funcional
claro
aquí al hacer un punto concat
dentro del reduce
aquí estás creando
un nuevo array
en cada iteración
y esto es bastante costoso
son 23 minutos
nada lol
pero son 23 minutos
de bastante buen nivel
y mira
aquí tenéis otro
más ejemplos
y tal
de cómo se podría hacer
con alternativas
os lo recomiendo mucho
porque hablan de cosas
bastante interesantes
de cuándo
se puede utilizar reduce
y cuándo
a lo mejor
no tiene tanto sentido
y yo estoy bastante de acuerdo
con lo que sea
si Surma y Jake
ya no están en Google
pero en ese momento
sí que estaban
y por lo tanto
entiendo que
eran ingenieros de Google
en ese momento
Google
como el que queráis decir
bueno total
a ver
esto se podría simplificar
yo esto lo he hecho
porque de nuevo
lo primero es
hacerlo
luego ya podríamos simplificarlo
una vez que ya tenemos
todo esto
la realidad
es que
le podemos volver
a dar un poco la vuelta
incluso no guardar
en variables
no guardar absolutamente nada
de hecho
si tú lo pones
te pones a mirar aquí
ya podemos ver
que podríamos
hacer la comparación
directamente
a lo mejor no sería
del todo correcto
pero podríamos decir
oye
si el store
del system name
directamente
es mayor o igual
al
y ya lo sacamos así
step numbers index
¿vale?
entonces ya le ponemos aquí
un return false
y ya nos podemos olvidar
de casi todo lo que hacemos abajo
la única diferencia
o sea
podemos quitar todo esto
todo esto ya no tiene sentido
y lo dejaríamos así
en tres líneas
sería exactamente lo mismo
solo que estamos
chequeándolo directamente
sin guardarlo en una variable
yo lo de la variable
siempre lo recomiendo
para que podáis entender
de dónde sale cada cosa
luego si lo queréis simplificar
lo podríais simplificar así
y esto
si no me equivoco
vale
pues la he liado parda
porque algo he hecho mal
que he hecho mal
algo he hecho mal
en alguna cosa me he equivocado
que no me he dado cuenta
pero alguna cosa
system name
system name
no se ha ejecutado
ah
execution error
esto es que alguna cosa
ha hecho mal
error output
ah
porque he puesto
current counter
ah
ves
esto en el linter
no me pasaría
vale
ah sí
ahora sí
ahora sí
vale
que claro
como no te indica el error
pues da bastante rabia
pues eso
sería lo mismo
pero sin utilizar variables
y quedaría mucho más sencillo
y la verdad que
no habría ningún tipo de problema
así lo podrías hacer también
¿qué le dirías a alguien
que está empeñado
en que la programación funcional
es una bala de plata
que sirve para todo?
que me da mucha pereza
¿es más fácil
debugger con variables?
sí totalmente
yo por eso
siempre lo haría primero
con variables
y luego si queréis
hacerlo un poquito más corto
y al final así
el tema de la programación funcional
a ver
la programación funcional
es súper interesante
y tiene un montón de ventajas
un montón
la verdad
pero llega un momento
en el que si tú te esfuerzas
tanto
en hacer que todo sea
programación funcional
llega un momento
que
que tiene un coste
de
de elegibilidad
a veces incluso
de rendimiento
dependiendo del lenguaje
de programación
hay algunos lenguajes
de programación
que están muy pensados
para programación funcional
javascript
por ejemplo
multiparadigma
en algunos casos
la programación funcional
funciona muy bien
pero hay en otros
que tiene un coste extra
de hecho
de eso hablan
muy interesantemente
en el vídeo
que os explicaba
de esta gente
con el tema de reduce
porque mucha gente
utiliza reduce
para poder utilizar
programación funcional
pero hablan de esto
de que
oye
es que
utilizas programación funcional
pero al final
el rendimiento
todo para no mutar
una variable
que tienes justamente
ahí al lado
y el rendimiento
pues es mucho peor
y vale la pena
realmente complicarlo
tanto para eso
cuando mejor
lo puedes hacer
mucho más fácil
claro
hay otros lenguajes
que sí que tiene sentido
pero cuando la gente
quiere utilizar
javascript
todo programación funcional
y entonces ya
para hacer eso
pues se ponen a meter
bibliotecas
como ramda
que es una biblioteca
muy interesante
pero que entonces
de repente
tiene
un montón de
se vuelve un pseudo lenguaje
ya no es javascript
ya tienes todo el código
lo tienes
atado a una biblioteca externa
para que puedas utilizar
tu programación funcional
y claro
eso es lo que realmente
es preocupante
¿sabes?
eso es lo que ya entonces
sí que dices
ostras
yo esto lo he visto con mis ojos
he visto proyectos caer
porque estaban
todo lleno de ramda
por todos los lados
con observables
ramda
rxjs
y todo esto
y claro
ya estás tan atado
todo el código
que ya no es javascript
es que es un pseudo lenguaje
que te has creado ahí
y hay gente
que entonces ya
hay muy poca gente
o que sabe por dónde
pillar el proyecto
o que estás atado
a versiones
de estas bibliotecas
entonces yo creo
que tiene sentido
la programación funcional
siempre que puedas
pero
como todo en esta vida
no hay balas de plata
en la programación
no hay nada
que sea blanco o negro
¿sabes?
siempre hay matices
y especialmente en javascript
que es multiparadigma
creo que la programación funcional
tiene sus casos de uso
muy interesantes
pero no siempre
son todos los casos de uso
no puedes forzar
a que sea todo
todo todo
todo programación funcional
porque al final
te va a reventar
bueno pues hablando
de la complejidad temporal
aquí ya podéis ver
complejidad temporal
pues nada
lo mismo
en el everi
pues tendríamos aquí
complejidad temporal
pues sería lineal
¿vale?
pues que según el número
de elementos
pues subiría
y la complejidad
que tendríamos
en cuanto espacial
también
sería
ON
¿vale?
también sería
ON
porque en este caso
sí que depende
de la entrada
¿no?
y dependiendo del número
de system names
veríamos que aquí
va a estar creciendo
el objeto
y cada vez el objeto
sería cada vez más grande
depende de la longitud
de los arrays
de en este caso
del system names
así que sería ON
¿no?
pensar que
todos los system names
podrían ser diferentes
por eso nos tenemos
que poner en el peor caso
y en el peor caso
que podría ser
que cada sistema
fuese diferente
podríamos tener ahí
que fuese N
así que ahí lo tendríamos
hay que conocer el tradeoff
de hacer el código
más legible y limpio
versus el rendimiento
totalmente
eso pasa siempre
de hecho
alguien me preguntaba
antes si esto
se podría hacer
con un map
que podría ser
un poquito más
poquito más
óptimo
tampoco es que
en este caso
sería muy
muy muy óptimo
pero bueno
esta sería un poco
la idea
en lugar de utilizar
el store
de esta forma
pues podríamos hacer
store.get
system name
system name
y aquí
pues teníamos que hacer
el set
del system name
y ya está
como no tiene una búsqueda
si tuvieras una
vale
la he liado
a ver
error output
invalid
ay
claro
esto no es así
con una asignación
eso soy yo
inventándome la sintaxis
pero bueno
esta sería un poco
la idea
utilizar un map
que sería una estructura
de como un diccionario
para poder tener aquí
el aquí del system name
para recuperarlo
y aquí para leerlo
sería una opción
yo creo que bastante
más legible
a mí me gustaría
yo utilizaría
seguramente esta
porque creo que tiene
todo el sentido del mundo
y que te puede ayudar
un montón
a entender la solución
a demostrar
que te sabes
otra estructura de datos
diferente al objeto
que está más óptima
y está más pensada
para este tipo de casos
aunque es verdad
que tampoco se aprovecha
al 100%
porque a lo mejor
si tuvieses búsquedas
y cosas así
sí que sería interesante
pero os invito
si no conocéis map
que le echéis un vistazo
tanto al map
como al set
que están bastante
bastante interesantes
el map al final
es para esto
para tener
un key value
y poder guardar
un key value
lo que aquí ten en cuenta
es que el key
tiene que ser único
que no se puede repetir
no entendía
luego entendí
y ahora no entiendo otra vez
bueno pero esto
porque es el tema del map
que a lo mejor
no lo habéis visto nunca
y en este caso
es un perfecto
caso de uso
para utilizar el map
porque es una estructura
de datos
que justamente
sirve para esto
y ya está
bien