Paso 1: Conectar el Scanner
Paso 2: No esperar a que el scanner haga algún ruido
Paso 3: Abrir la aplicación "Escáner de Documentos" que ya viene instalada
Paso 4: esperar a que detecte el scanner
Paso 5: Have fun
Códigos de ejemplo para aprender distintas tecnologías, o lo que sucede cuando a una cuarentona se la deja sola con una computadora
Paso 1: Conectar el Scanner
Paso 2: No esperar a que el scanner haga algún ruido
Paso 3: Abrir la aplicación "Escáner de Documentos" que ya viene instalada
Paso 4: esperar a que detecte el scanner
Paso 5: Have fun
Mi Linux Mint es el siguiente:
System:
Kernel: 6.17.0-35-generic arch: x86_64 bits: 64 compiler: gcc v: 13.3.0 clocksource: tsc
Desktop: Cinnamon v: 6.6.7 tk: GTK v: 3.24.41 wm: Muffin v: 6.6.3 vt: 7 dm: LightDM v: 1.30.0
Distro: Linux Mint 22.3 Zena base: Ubuntu 24.04 noble
Machine:
Type: Laptop System: LENOVO product: 83A1 v: Lenovo V15 G4 IRU
En esta distro se puede acceder al menú de inicio con la tecla Windows.
A esta información se llega poniendo "About" en la caja de búsqueda del menú inicio (¿se le dice así en Linux?) y aparecerá la pantalla de Información del Sistema (Este pantallazo es de cuando ya había cambiado mi sistema a español, las instrucciones más abajo).
Y ahora el tutorial:
Primero: aumentar el tamaño de fuente porque por defecto los Linux muestran todo muy chiquito. Nos vomos a la opción All Applications -> Accesibility-> Visual y elegimos Large Text:
Luego vamos a All Applications -> Font Selection (debajo del que está resaltado en la imagen)
En esta ventana podemos configurar el tamaño de fuente de todo el sistema, yo le puse 11 a todo:
Segundo:. El teclado. El layout "Spanish (Latin America no Dead keys)" no coincide con mi teclado. Para corregirlo hay que ir a Inicio y escribir Keyboard en la caja de búsqueda
En la ventana que aparece, podremos elegir un nuevo layout haciendo click en el botón con el signo +
Escritorio: Le hacemos click derecho y elegimos Change Desktop Background:
El signo + permite elegir una carpeta conn las imágenes y la pestaña Settings permite configurar el tamaño y el tiempo que se verán en el escritorio
Faltan los íconos, le hacemos click derecho a la barra de tareas y elegimos System Settings->Desktop
Luego quise aumentarle el tamaño al panel (barra de tareas). Nos vamos a System Settings -> Panel o también haciéndole click derecho al Panel y eligiendo la primera opción: Panel Settings. En la sección Customize se puede aumentar el alto del Panel, esto hará que el panel (y los ícoonos de los programas) sean más grandes.
El resultado no está mal:
En el menú de inicio elegimos Language, aparecerá esta ventana:
Aquí podemos instalar Lenguajes. Nos va a pedir la contaseña.
Para que se haga efectivo el cambio se debe reiniciar el sistema:
Update un día después: Al cambiar el lenguaje del sistema, Linux me creó nuevas carpetas en mi carpeta home:
Los archivos que creé o descargué antes del cambio de idioma se quedaron en las carpetas Documents, Pictures y Downloads. Las nuevas carpetas, y que son las que aparecen en la lista de la izquierda, son respectivamente: Documentos, Imágenes y Descargas. Un detalle es que esto sólo ha sucedido con las carpetas que tenían archivos dentro, las que estaban vacías (Music, Desktop, etc) ya no aparecen.
Ah, cómo echo de menos el linux. Y antes de que Microsoft me obligue a usar su AI (mi odio a la AI es otra historia: sé lo que hay detrás, sé cómo funciona, y he visto cómo nos está llevando al desastre ecológico y social), y me obligue a cederle más data personal de la que ya le doy, quiero tener la opción de usar un linux y mandarlos a dar por culo.
Y mejor no menciono Windows Recall, eso ya es un círculo más profundo en el infierno.
rant/
Mi lucha contra la AI incluye también a Google y otras empresas por ahi: lo único smart que tengo es mi teléfono del 2018 junto a un martillo por si se le ocurre hacer un ruido raro (mi tablet del 2014 no cuenta). El beneficio que da la AI a una persona común y corriente es cero, no hace nada que no hacíamos ya usando el cerebro y la wikipedia, y la obsesión por la productividad no nos ha dado aire más limpio ni comida más barata. Ojalá la burbuja reviente de una vez.
/rantY ahora al tutorial. Mi laptop es una Lenovo del año pasado (yo misma me sorprendo: ¡estoy usando hardware de menos de una década de edad!) así que puedo meterle todo el software patea-hardware que me de la gana, así que le voy a meter la última versión del Linux Mint https://linuxmint-installation-guide.readthedocs.io/en/latest/
Antes tenía que crearme un USB booteable. Elegí el disco duro que tengo tirado de una laptop del 2011 (y que ya murió) al que hice que me lo pusieran en uno de esos adaptadores que permiten usarlo como disco duro externo.
Paso 0: Siempre: backupear todo.
Instrucciones para crear el USB booteable aquí: https://linuxmint-installation-guide.readthedocs.io/en/latest/burn.html Linux Mint recomienda usar la aplicación Etcher.
Para bootear desde USB seguí las instrucciones de esta web: https://support.lenovo.com/pe/es/solutions/ht500217
En Windows 11 hay que ir a configuración -> Sistema ->Recuperación
De ahí vamos a Arranque Avanzado -> Reiniciar
Windows nos mostrará este menú, hay que elegir "Usar un Dispositivo":
Aquí el sistema arrancará desde el Live Linux dentro del USB. En la esquina superior izquierda nos aparecerá esta opción:
Entramos a esta opción, una vez que termine de cargar el instalador nos mostrará la opción que necesitamos ya seleccionada:
Ya nos está prometiendo no trastearnos el Windows y que nos dará la opción de elegir el sistema operativo una vez terminada la instalación. Le damos continuar.
Mi laptop tiene un disco duro de 500 gigas particionado en C y D (mitad y mitad aproximadamente). En la imagen se ve la partición C (nvme0n1p3), a la derecha está la D (nvme0np1p5), se las reconoce por el tamaño:
Aquí debo resaltar que MI PARTICIÓN D ESTÁ VACÍA.
Para el "Device for boot loader installation" le dejamos el dispositivo /dev/nvme0n1 que es mi disco duro, le damos continuar:
Yo le dejé el tamaño de partición por defecto, está cogiendo mi partición D (vacía). Va a crear una partición nueva: nvme0n1p6
Hasta aquí podemos retroceder todas las veces que queramos.
Le damos continuar y nos encomendamos a Linus Torvalds.
Primero va a pedir elegir si queremos descargar códecs, ingresar la contraseña del wifi, y el idioma del teclado (yo elegí Spanish LatinAmérica No Dead Keys), y los datos de nuestra cuenta de usuario:
A partir de aquí es darle "Continue". En mi caso la instalación demoró menos de diez minutos.
Al terminar la instalación yo le puse "Continue Testing" para poder apagar la laptop y quitar el USB.
Al iniciar nuevamente el sistema aparece este menú:
Todo bien y ya tenemos el el doble booteo Linux/Windows. Y pude confirmar que no tocó mi partición C:
Algo bonito: el Linux Mint tiene la misma combinación de teclas de Windows:
Windows+D: mostrar escritorio
Windows+E: Abrir el explorador
Shift + Print Screen: Selecionar un área de la pantalla a copiar o guardar. En mi lenovo es Shiift+Fn+Print Screen
Tengo que probar aún Windows+Shiift+S que es para capturar áreas de la pantalla (update: abre las opciones de volumen) y ver si me reconoce el scanner, pero eso es para otro día.
Basado en los códigos de Mike Gold
https://www.c-sharpcorner.com/article/generating-maze-using-C-Sharp-and-net/
https://www.c-sharpcorner.com/article/eater-game-ii-the-stone-maze/
y el algoritmo de backtracking para generar un laberinto https://professor-l.github.io/mazes/
Este algoritmo de Python usa el pseudocódigo de una web que ya no existe pero que es la que usé para aprender la técnica https://gist.github.com/fitzterra/9491696
Primero debía saber cómo "pintar" el laberinto, por ello busqué el evento "Paint" en el formulario (la ventanita) en el código de Mike:
El truco está en los objetos "g" y "e". El evento "Paint" se dispara al crear la ventana o maximizarla. Este evento recibe un objeto "e" del tipo PaintEventArgs con el cual creamos el objeto "g" del tipo "Graphics". Es con este objeto con el que se va a pintar el laberinto.
El código mostrado llama al método "Draw" ("TheMaze" es un objeto de la clase "Maze", creada por Mike e incluida en su código).
El método "Draw" llama a otro método "Draw" en otra clase creada por Mike llamada "Cell". Nos vamos para allá:
He aquí el código para pintar o dibujar el laberinto. Todo se reduce a dibujar líneas con el método "DrawLine" del objeto "g".
Yo empecé por dibujar una grilla, con todas las celdas del laberinto. Haría mi laberinto "tumbando paredes" en la grilla.
Como no entendí nada del código de Mike, y como ya estaba perdiendo mucho tiempo intentando entenderlo, supe que debía crear mi propio código. El método "Draw" de la clase "Cell" de Mike me dio otra pista: él declara cuatro paredes, entonces yo también debía crear cuatro paredes (y deduje que serían cuatro paredes por celda). Lo hice mediante esta estructura:
Hice mi generador de laberintos un poco al estilo de Mike: creé una clase aparte llamada "Maze" con un método llamado "DibujarLab" que se llama desde el evento "Paint" del formulario. Y ahí se acaban las similitudes.
Y mi código se puede bajar de aquí :)
La variable "padd" determina el tamaño de las celdas que conforman el laberinto.
Acerca de la variable "PrimeraVez": Si su valor es falso, evitará crear una nueva matriz "celda" al minimizar y maximizar el formulario (en el evento "Load", "PrimeraVez" debe ser true), pero su valor se puede dejar como verdadero si se desea generar un nuevo laberinto cuando se minimiza y maximiza la ventana.
Para generar números aleatorios: Se tiene que usar la clase Random que viene con el .Net. Yo creé un objeto llamado "currentCelda" y es a partir de este objeto que se escoge la celda inicial y la celda siguiente (de las cuatro inicialmente disponibles) por donde se empezará a "tumbar paredes". Si se crea otro objeto aleatorio Random para escoger la celda siguiente (en el método "cogerCelda"), el laberinto no queda bien.
El método "cogerCelda" es donde se escoge la celda siguiente, la pared entre la celda actual y la siguiente es la que se tumbará. En realidad este método no sabe si hay 1,2,3 ó 4 celdas siguientes intactas. Sólo sabe que hay al menos una. "cogerCelda" es como el juego del bingo: no se detendré hasta que haya un ganador, es decir: no saldrá del bucle "while" hasta que el número aleatorio coincida con una celda con todas sus paredes intactas. Según su valor devuelto, se sabrá si se debe tumbar una pared Norte, Sur, Este u Oeste y cuál será la siguiente celda por donde se continuará tumbando paredes.
A la hora de dibujar el laberinto consideré el primer índice de la matriz "celda" como las filas, y el segundo como las columnas. Así a la coordenada "x" le corresponde el segundo índice (ubicación horizontal), y a la coordenada "y" el primer índice (ubicación vertical). El método DrawLine necesita estas coordenadas para determinar los puntos inicial y final de las líneas que dibujará. Es fácil confundirse. A mí me pasó.
Ahora un pantallazo de cómo queda el laberinto:
¿Por qué no hacerlo triangular?
Esta vez el número de columnas va aumentado a medida que el laberinto "crece". Por ello, en lugar de crear una matriz cuadrada, declaré lo que en inglés se llama "jagged array". Se trata de una matriz que puede tener distinto número de columnas por cada fila. La cantidad de columnas por fila está dada por esta fórmula, muy fácil de deducir en realidad:
n° de columnas = (2*n° de filas) + 1
El compilador prioriza multiplicaciones y divisiones por encima de sumas y restas, por lo que los paréntesis pueden omitirse.
A la hora de generar la matriz "celda" sólo se tienen tres paredes por celda, por ello esta vez la estructura "celda" sólo tiene tres "puntos cardinales": L1, L2 y piso (lado derecho, lado izquierdo y piso). Dependiendo de su ubicación, las celdas podían tener el piso arriba o abajo, mientras que L1 y L2 no cambian su ubicación.
Lo más difícil fue dibujar las celdas en el lugar que les corresponde pues el laberinto es triangular, mientras que el sistema de coordenadas en la ventana es rectangular. Para facilitarme las cosas, primero dibujé las celdas en un sentido, y luego las que están en el otro, así al final sólo se debe juntar todo (por ello hay dos bucles dentro del bucle principal en el método "DibujarLab"):
El resultado es éste:
Por alguna razón siempre me sale que la última fila tiene una pared recta. No sé porqué, pero no importa, porque si se hace que el bucle principal (al que le corresponde la variable "i") en el método DibujarLab vaya de 0 hasta menos de "pisos-1" en lugar de "pisos":
"pisos" es la variable que determina el número máximo de filas que tendrá la matriz que genera el laberinto triangular.
¿Cuándo compré este scanner? ¿2012? ¿cuándo lo usé por última vez? ¿en una laptop con Windows 10 allá por el 2024 que ni siquiera era mía?
Bueno, ahora tengo una laptop con Windows 11 y me pasó que tenía que digitalizar unos documentos. Así que me fui a la web de canon a bajarme el driver de mi viejo scanner
En la web de canon España y la de Europa me sale esto:
Funcionó y sin reiniciar la laptop, como prueba escaneé este dibujo:
Esta prueba la hice en java 11 y 17. Se basa en crear un ArrayList cuyos elementos son arrays, para estos ejemplos estoy usando IntelliJ:
public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};
List<String[]> unaListaDeArrays = new ArrayList<>();
unaListaDeArrays.add(unArray);
unArray[0] = "Cucky";
unArray[1] = "Joe Pino";
unArray[2] = "Horacio";
unArray[3] = "Pepe Lota";
unaListaDeArrays.add(unArray);
for (int i = 1; i < unaListaDeArrays.size(); i++) {
for (String s : unaListaDeArrays.get(i))
System.out.println(s + ", ");
}
System.exit(0);
}
}
Como los arrays son almacenados en el ArrayList por referencia (es decir que lo que se guarda no es el array, es su dirección de memoria) el resultado es:
He perdido a los presentadores y al productor de 31 Minutos y me he quedado sólo con los cantantes. Esto no puede ser. Si se almacenara por valor, el arrayList recibiría una copia de los arrays de forma automática, pero por diseño de la JVM no es así.
Para resolverlo hay que crear una copia del array unArray en memoria antes de añadirlo al arrayList, esto es muy fácil de hacer, una forma es usando el operador "new":public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};
List<String[]> unaListaDeArrays = new ArrayList<>();
unaListaDeArrays.add(unArray);
unArray = new String[] {"Cucky", "Joe Pino", "Horacio", "Pepe Lota"};
unaListaDeArrays.add(unArray);
for (int i = 1; i < unaListaDeArrays.size(); i++) {
for (String s : unaListaDeArrays.get(i))
System.out.println(s + ", ");
}
System.exit(0);
}
}
Ya quedó bien:
public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};
List<String[]> unaListaDeArrays = new ArrayList<>();
unaListaDeArrays.add(unArray.clone());
unArray[0] = "Cucky";
unArray[1] = "Joe Pino";
unArray[2] = "Horacio";
unArray[3] = "Pepe Lota";
unaListaDeArrays.add(unArray.clone());
for (int i = 1; i < unaListaDeArrays.size(); i++) {
for (String s : unaListaDeArrays.get(i))
System.out.println(s + ", ");
}
System.exit(0);
}
}
El resultado es:
Hora de arreglar esos dos bucles anidados del final, para eso se pueden usar los streams de Java:
public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};
List<String[]> unaListaDeArrays = new ArrayList<>();
unaListaDeArrays.add(unArray.clone());
unArray[0] = "Cucky";
unArray[1] = "Joe Pino";
unArray[2] = "Horacio";
unArray[3] = "Pepe Lota";
unaListaDeArrays.add(unArray.clone());
unaListaDeArrays.stream().forEach(arr ->
Arrays.stream(arr).forEach(s -> System.out.println(s + ", "))
);
System.exit(0);
}
}