Una forma sencilla y rápida de aprender JAVA, observando y deduciendo cómo se comporta el lenguaje a través de ejemplos prácticos.

Archivo del blog

lunes, 8 de julio de 2024

Juegos IV.2. Tres en Raya (GUI).

Esta versión del código crea una interfaz gráfica para el juego de tres en raya con las siguientes características:

1- Usa una imagen para representar el tablero.
2- Los jugadores hacen clic directamente en las casillas para realizar sus jugadas.
3- Las X's y O's se dibujan en el tablero con diferentes colores.
4- Detecta automáticamente cuando hay un ganador o un empate.
5- Muestra mensajes de victoria o empate y reinicia el juego.


Código Java (TresEnRayaGUI.java):

package tresenrayagui;

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;

public class TresEnRayaGUI extends JFrame {

    private static final int CELL_SIZE = 100;
    private static final int BOARD_SIZE = 3;
    private static final int WINDOW_WIDTH = CELL_SIZE * BOARD_SIZE + 40;
    private static final int WINDOW_HEIGHT = CELL_SIZE * BOARD_SIZE + 160;

    private final char[][] tablero = new char[BOARD_SIZE][BOARD_SIZE];
    private char jugadorActual = 'X';
    private final JPanel boardPanel;
    private final JLabel turnoLabel;
    private final JLabel puntajeLabel;
    private int puntosX = 0, puntosO = 0;

    public TresEnRayaGUI() {
        setTitle("Tres en Raya");
        setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);

        // Panel de información mejorado
        JPanel infoPanel = new JPanel(new GridLayout(2, 1, 0, 5));
        infoPanel.setBackground(new Color(230, 230, 250));
        infoPanel.setBorder(new CompoundBorder(
                new LineBorder(new Color(100, 100, 100), 2),
                new EmptyBorder(10, 10, 10, 10)
        ));

        Font mathFont = new Font("Cambria Math", Font.BOLD, 18);
        if (mathFont.getFamily().equals("Dialog")) {
            mathFont = new Font("Arial", Font.BOLD, 18);
        }

        turnoLabel = new JLabel("Turno del jugador: X", SwingConstants.CENTER);
        turnoLabel.setFont(mathFont);
        puntajeLabel = new JLabel("X: 0 | O: 0", SwingConstants.CENTER);
        puntajeLabel.setFont(mathFont);

        infoPanel.add(turnoLabel);
        infoPanel.add(puntajeLabel);
        add(infoPanel, BorderLayout.NORTH);

        inicializarTablero();

        boardPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                dibujarTablero(g);
            }
        };
        boardPanel.setPreferredSize(new Dimension(CELL_SIZE * BOARD_SIZE, CELL_SIZE * BOARD_SIZE));
        boardPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int col = e.getX() / CELL_SIZE;
                int row = e.getY() / CELL_SIZE;
                realizarJugada(row, col);
            }
        });

        JPanel centerPanel = new JPanel(new GridBagLayout());
        centerPanel.setBackground(new Color(230, 230, 250));
        centerPanel.add(boardPanel);

        add(centerPanel, BorderLayout.CENTER);
    }

    private void inicializarTablero() {
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                tablero[i][j] = ' ';
            }
        }
    }

    private void dibujarTablero(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // Dibujar fondo degradado
        GradientPaint gp = new GradientPaint(0, 0, new Color(200, 220, 240), CELL_SIZE * BOARD_SIZE, CELL_SIZE * BOARD_SIZE, new Color(220, 240, 255));
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, CELL_SIZE * BOARD_SIZE, CELL_SIZE * BOARD_SIZE);

        // Dibujar líneas del tablero
        g2d.setColor(new Color(100, 100, 100));
        g2d.setStroke(new BasicStroke(2));
        for (int i = 1; i < BOARD_SIZE; i++) {
            g2d.drawLine(i * CELL_SIZE, 0, i * CELL_SIZE, BOARD_SIZE * CELL_SIZE);
            g2d.drawLine(0, i * CELL_SIZE, BOARD_SIZE * CELL_SIZE, i * CELL_SIZE);
        }

        // Dibujar X y O
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (tablero[i][j] == 'X') {
                    dibujarX(g2d, j * CELL_SIZE, i * CELL_SIZE);
                } else if (tablero[i][j] == 'O') {
                    dibujarO(g2d, j * CELL_SIZE, i * CELL_SIZE);
                }
            }
        }
    }

    private void dibujarX(Graphics2D g2d, int x, int y) {
        g2d.setColor(new Color(220, 20, 60));
        g2d.setStroke(new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g2d.draw(new Line2D.Double(x + 20, y + 20, x + CELL_SIZE - 20, y + CELL_SIZE - 20));
        g2d.draw(new Line2D.Double(x + CELL_SIZE - 20, y + 20, x + 20, y + CELL_SIZE - 20));
    }

    private void dibujarO(Graphics2D g2d, int x, int y) {
        g2d.setColor(new Color(30, 144, 255));
        g2d.setStroke(new BasicStroke(4));
        g2d.draw(new Ellipse2D.Double(x + 20, y + 20, CELL_SIZE - 40, CELL_SIZE - 40));
    }

    private void realizarJugada(int row, int col) {
        if (tablero[row][col] == ' ') {
            tablero[row][col] = jugadorActual;
            boardPanel.repaint();
            if (verificarGanador(row, col)) {
                if (jugadorActual == 'X') {
                    puntosX++;
                } else {
                    puntosO++;
                }
                JOptionPane.showMessageDialog(this, "¡El jugador " + jugadorActual + " ha ganado!");
                reiniciarJuego();
            } else if (tableroLleno()) {
                JOptionPane.showMessageDialog(this, "¡Empate!");
                reiniciarJuego();
            } else {
                jugadorActual = (jugadorActual == 'X') ? 'O' : 'X';
                actualizarInfoLabel();
            }
        }
    }

    private boolean verificarGanador(int row, int col) {
        return (tablero[row][0] == jugadorActual && tablero[row][1] == jugadorActual && tablero[row][2] == jugadorActual)
                || (tablero[0][col] == jugadorActual && tablero[1][col] == jugadorActual && tablero[2][col] == jugadorActual)
                || (row == col && tablero[0][0] == jugadorActual && tablero[1][1] == jugadorActual && tablero[2][2] == jugadorActual)
                || (row + col == 2 && tablero[0][2] == jugadorActual && tablero[1][1] == jugadorActual && tablero[2][0] == jugadorActual);
    }

    private boolean tableroLleno() {
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (tablero[i][j] == ' ') {
                    return false;
                }
            }
        }
        return true;
    }

    private void reiniciarJuego() {
        inicializarTablero();
        jugadorActual = 'X';
        actualizarInfoLabel();
        boardPanel.repaint();
    }

    private void actualizarInfoLabel() {
        turnoLabel.setText("Turno del jugador: " + jugadorActual);
        puntajeLabel.setText("X: " + puntosX + " | O: " + puntosO);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TresEnRayaGUI().setVisible(true));
    }
}


Resultado:



jueves, 4 de julio de 2024

Juegos IV. Tres en Raya.


Código Java (TresEnRaya.java):

package tresenraya;

import java.util.Scanner;

public class TresEnRaya {

    private static final char[] JUGADORES = {'X', 'O'};
    private static final String LINEA_SUPERIOR = "  ╔═══╦═══╦═══╗";
    private static final String LINEA_MEDIA = "  ╠═══╬═══╬═══╣";
    private static final String LINEA_INFERIOR = "  ╚═══╩═══╩═══╝";

    private static final char[][] tablero = new char[3][3];
    private static final Scanner scanner = new Scanner(System.in);
    private static int jugadorActual = 0;

    public static void main(String[] args) {
        try (scanner) {
            while (true) {
                if (jugar()) {
                    break;
                }
            }
        }
    }

    private static boolean jugar() {
        inicializarTablero();
        while (true) {
            dibujarTablero();
            if (!realizarJugada()) {
                return false;
            }
            if (verificarGanador()) {
                dibujarTablero();
                System.out.println("¡El jugador " + JUGADORES[jugadorActual] + " ha ganado!");
                return true;
            }
            if (tableroLleno()) {
                dibujarTablero();
                System.out.println("¡Empate!");
                return true;
            }
            jugadorActual = 1 - jugadorActual;
        }
    }

    private static void inicializarTablero() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                tablero[i][j] = ' ';
            }
        }
    }

    private static void dibujarTablero() {
        System.out.println(LINEA_SUPERIOR);
        for (int i = 2; i >= 0; i--) {
            System.out.print((i + 1) + "-║");
            for (int j = 0; j < 3; j++) {
                System.out.print(" " + tablero[i][j] + " ║");
            }
            System.out.println();
            if (i > 0) {
                System.out.println(LINEA_MEDIA);
            }
        }
        System.out.println(LINEA_INFERIOR);
        System.out.println("    A   B   C");
    }

    private static boolean realizarJugada() {
        System.out.println("Jugador " + JUGADORES[jugadorActual] + ", ingresa coordenada: ");
        try {
            String entrada = scanner.nextLine().toUpperCase().trim();
            if (entrada.length() != 2) {
                throw new IllegalArgumentException();
            }

            int columna = entrada.charAt(0) - 'A';
            int fila = Character.getNumericValue(entrada.charAt(1)) - 1;

            if (fila < 0 || fila > 2 || columna < 0 || columna > 2 || tablero[fila][columna] != ' ') {
                System.out.println("Jugada inválida. Intenta de nuevo.");
                return true;
            }
            tablero[fila][columna] = JUGADORES[jugadorActual];
            return true;
        } catch (IllegalArgumentException e) {
            System.out.println("Entrada inválida. ¿Deseas salir? (s/n)");
            return !scanner.nextLine().trim().equalsIgnoreCase("s");
        }
    }

    private static boolean verificarGanador() {
        for (int i = 0; i < 3; i++) {
            if (tablero[i][0] != ' ' && tablero[i][0] == tablero[i][1] && tablero[i][1] == tablero[i][2]) {
                return true;
            }
            if (tablero[0][i] != ' ' && tablero[0][i] == tablero[1][i] && tablero[1][i] == tablero[2][i]) {
                return true;
            }
        }
        return (tablero[0][0] != ' ' && tablero[0][0] == tablero[1][1] && tablero[1][1] == tablero[2][2])
                || (tablero[0][2] != ' ' && tablero[0][2] == tablero[1][1] && tablero[1][1] == tablero[2][0]);
    }

    private static boolean tableroLleno() {
        for (char[] fila : tablero) {
            for (char celda : fila) {
                if (celda == ' ') {
                    return false;
                }
            }
        }
        return true;
    }
}


Resultado:

run:
  ╔═══╦═══╦═══╗
3-║   ║   ║   ║
  ╠═══╬═══╬═══╣
2-║   ║   ║   ║
  ╠═══╬═══╬═══╣
1-║   ║   ║   ║
  ╚═══╩═══╩═══╝
    A   B   C
Jugador X, ingresa coordenada:
b1
  ╔═══╦═══╦═══╗
3-║   ║   ║   ║
  ╠═══╬═══╬═══╣
2-║   ║   ║   ║
  ╠═══╬═══╬═══╣
1-║   ║ X ║   ║
  ╚═══╩═══╩═══╝
    A   B   C
Jugador O, ingresa coordenada:
b2
  ╔═══╦═══╦═══╗
3-║   ║   ║   ║
  ╠═══╬═══╬═══╣
2-║   ║ O ║   ║
  ╠═══╬═══╬═══╣
1-║   ║ X ║   ║
  ╚═══╩═══╩═══╝
    A   B   C
Jugador X, ingresa coordenada:
c3
  ╔═══╦═══╦═══╗
3-║   ║   ║ X ║
  ╠═══╬═══╬═══╣
2-║   ║ O ║   ║
  ╠═══╬═══╬═══╣
1-║   ║ X ║   ║
  ╚═══╩═══╩═══╝
    A   B   C
Jugador O, ingresa coordenada:
 

martes, 2 de julio de 2024

Generación de laberintos I.2. Algoritmo de Aldous-Broder.

El Algoritmo de Aldous-Broder es otro método para generar un laberinto aleatorio. Funcionamiento para la generación es el siguiente:

    1. Comenzar en un vértice aleatorio del grafo.
    2. Elegir un vecino aleatorio del vértice actual.
    3. Si el vecino no ha sido visitado, añadir la arista entre el vértice actual y el vecino al árbol de expansión.
    4. Moverse al vecino elegido (sea visitado o no).
    5. Repetir los pasos 2-4 hasta que todos los vértices hayan sido visitados.

Este algoritmo es simple pero ineficiente, especialmente para grafos grandes, ya que puede tomar mucho tiempo para visitar todos los vértices.

 

Código (AldousBroderMaze.java):

package aldousbrodermaze;

import java.util.*;

public class AldousBroderMaze {

    private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private final int width;
    private final int height;
    private final boolean[][] maze;

    public AldousBroderMaze(int width, int height) {
        this.width = width;
        this.height = height;
        this.maze = new boolean[height * 2 + 1][width * 2 + 1];
    }

    public void generateMaze() {
        Random rand = new Random();
        int x = rand.nextInt(width) * 2 + 1;
        int y = rand.nextInt(height) * 2 + 1;
        int unvisited = width * height - 1;

        maze[y][x] = true;

        while (unvisited > 0) {
            int[] direction = DIRECTIONS[rand.nextInt(DIRECTIONS.length)];
            int newX = x + direction[0] * 2;
            int newY = y + direction[1] * 2;

            if (newX > 0 && newX < maze[0].length && newY > 0 && newY < maze.length) {
                if (!maze[newY][newX]) {
                    maze[newY][newX] = true;
                    maze[y + direction[1]][x + direction[0]] = true;
                    unvisited--;
                }
                x = newX;
                y = newY;
            }
        }
    }

    public void printMaze() {
        for (boolean[] row : maze) {
            for (boolean cell : row) {
                System.out.print(cell ? "  " : "██");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        AldousBroderMaze maze = new AldousBroderMaze(10, 10);
        maze.generateMaze();
        maze.printMaze();
    }
}


Resultado:

run:
██████████████████████████████████████████
██              ██  ██      ██          ██
██  ██████████████  ██████  ██  ██████████
██              ██      ██  ██      ██  ██
██  ██  ██████████████  ██  ██  ██████  ██
██  ██      ██          ██  ██          ██
██  ██████████████  ██████  ██  ██████  ██
██              ██  ██          ██  ██  ██
██  ██████████  ██  ██████  ██  ██  ██████
██  ██  ██              ██  ██      ██  ██
██  ██  ██████████████████  ██████  ██  ██
██          ██  ██      ██  ██          ██
██████████  ██  ██████  ██  ██  ██  ██████
██          ██  ██  ██      ██  ██      ██
██████████  ██  ██  ██████████  ██████████
██              ██      ██  ██      ██  ██
██████████████  ██  ██████  ██  ██████  ██
██                      ██  ██  ██      ██
██████████  ██  ██████  ██  ██  ██████  ██
██          ██  ██                      ██
██████████████████████████████████████████
BUILD SUCCESSFUL (total time: 0 seconds)


domingo, 26 de mayo de 2024

Proyecto Ajedrez I.0: Descripción de las reglas

Objetivo del Juego de Ajedrez

El objetivo del ajedrez es dar jaque mate al rey oponente, lo que significa que el rey está en una posición de ataque y no puede escapar.

El Tablero

    El tablero es una cuadrícula de 8x8, con 64 casillas alternadas en colores claros y oscuros.
    Las columnas se denominan de la 'a' a la 'h', y las filas del '1' al '8'.

Colocación de las Piezas

    Fila 1 (de las blancas) y Fila 8 (de las negras): Torre (T), Caballo (C), Alfil (A), Dama (Q), Rey (K), Alfil (A), Caballo (C), Torre (T).
    Filas 2 (blancas) y 7 (negras): Peones (P).
    Las piezas blancas empiezan en las filas 1 y 2, las negras en las filas 7 y 8.


     ┌─────────────────┐
    8┤ t c a q k a c t │
    7┤ p p p p p p p p │
    6┤ . . . . . . . . │
    5┤ . . . . . . . . │
    4┤ . . . . . . . . │
    3┤ . . . . . . . . │
    2┤ P P P P P P P P │
    1┤ T C A Q K A C T │
     └─┬─┬─┬─┬─┬─┬─┬─┬─┘
       A B C D E F G H



Movimientos de las Piezas

    Peón (P)
        Movimiento: Avanza una casilla hacia adelante. En su primer movimiento, puede avanzar dos casillas.
        Captura: Una casilla en diagonal hacia adelante.
        Captura al paso: Un peón que avanza dos casillas desde su posición inicial puede ser capturado "al paso" por un peón enemigo como si solo hubiera avanzado una casilla. Esto solo es posible inmediatamente después del movimiento del peón.

    Torre (T)
        Movimiento: Vertical y horizontalmente, tantas casillas como desee.
        Captura: Igual que el movimiento.

    Caballo (C)
        Movimiento: Forma de 'L' (dos casillas en una dirección y una en perpendicular). Puede saltar sobre otras piezas.
        Captura: Igual que el movimiento.

    Alfil (A)
        Movimiento: Diagonalmente, tantas casillas como desee.
        Captura: Igual que el movimiento.

    Dama (Q)
        Movimiento: Vertical, horizontal y diagonalmente, tantas casillas como desee.
        Captura: Igual que el movimiento.

    Rey (K)
        Movimiento: Una casilla en cualquier dirección.
        Captura: Igual que el movimiento.
        Enroque: Movimiento especial en colaboración con una torre (ver detalles abajo).

Movimientos Especiales

    Enroque:
        Condiciones:
            El rey y la torre implicada no deben haberse movido previamente.
            No debe haber piezas entre el rey y la torre.
            El rey no puede estar en jaque, pasar por casillas bajo ataque, ni terminar en jaque.
        Movimiento:
            Enroque corto: Rey mueve dos casillas hacia la torre del lado rey, y la torre se coloca a su lado.
            Enroque largo: Rey mueve dos casillas hacia la torre del lado dama, y la torre se coloca a su lado.

    Captura al paso: Un peón que avanza dos casillas desde su posición inicial puede ser capturado al paso por un peón enemigo en la columna adyacente que se encuentra en la quinta fila (blancas) o cuarta fila (negras).

    Promoción de Peón: Cuando un peón alcanza la octava fila, debe ser promovido a una dama, torre, alfil o caballo, a elección del jugador.

Reglas de Jaque y Jaque Mate

    Jaque: El rey está bajo ataque. El jugador debe mover el rey, capturar la pieza atacante o interponer otra pieza para bloquear el ataque.
    Jaque Mate: El rey está bajo ataque y no puede escapar. El juego termina y el jugador que dio el jaque mate gana.

Otras Reglas

    Tablas: El juego puede terminar en empate por varias razones, como repetición de jugadas, rey ahogado (rey no está en jaque pero no tiene movimientos legales), acuerdo mutuo, o si 50 movimientos han pasado sin captura ni movimiento de peón.

 

domingo, 19 de mayo de 2024

Gráfica de un mapa de calor a partir de una matriz.

Este programa crea una ventana que muestra un mapa de calor basado en los valores de la matriz proporcionada. Los valores más bajos se representan en negro y los valores más altos en blanco, con una escala de grises entre ellos.

Matriz de distancias:

    0  185  905  911  236  173  549   85  506  972  911  681
  185    0  421  824  270  350   79  275  666  831  259  251
  905  421    0  286  136  338  764  249  881  508  902  798
  911  824  286    0  924  282  815   40  242  571  448  886
  236  270  136  924    0   88  521  140  345  799  544  295
  173  350  338  282   88    0  584  254   61   76  931  870
  549   79  764  815  521  584    0  353  795  547  213  198
   85  275  249   40  140  254  353    0  181  682  427  539
  506  666  881  242  345   61  795  181    0  618  775  521
  972  831  508  571  799   76  547  682  618    0  734  462
  911  259  902  448  544  931  213  427  775  734    0  162
  681  251  798  886  295  870  198  539  521  462  162    0


Código Java (HeatMap.java):

import javax.swing.*;
import java.awt.*;

public class HeatMap extends JPanel {
    private final int[][] data;
    private final int maxValue;
    private final int minValue;

    public HeatMap(int[][] data) {
        this.data = data;
        this.maxValue = findMaxValue(data);
        this.minValue = findMinValue(data);
    }

    private int findMaxValue(int[][] data) {
        int max = Integer.MIN_VALUE;
        for (int[] row : data) {
            for (int value : row) {
                if (value > max) {
                    max = value;
                }
            }
        }
        return max;
    }

    private int findMinValue(int[][] data) {
        int min = Integer.MAX_VALUE;
        for (int[] row : data) {
            for (int value : row) {
                if (value < min) {
                    min = value;
                }
            }
        }
        return min;
    }

    private Color getColor(int value) {
        float normalizedValue = (float)(value - minValue) / (maxValue - minValue);
        int gray = (int)(normalizedValue * 255);
        return new Color(gray, gray, gray);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int cellWidth = getWidth() / data[0].length;
        int cellHeight = getHeight() / data.length;
        for (int row = 0; row < data.length; row++) {
            for (int col = 0; col < data[row].length; col++) {
                g.setColor(getColor(data[row][col]));
                g.fillRect(col * cellWidth, row * cellHeight, cellWidth, cellHeight);
            }
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(600, 600);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Heat Map");
        int[][] data = {
            {0, 185, 905, 911, 236, 173, 549, 85, 506, 972, 911, 681},
            {185, 0, 421, 824, 270, 350, 79, 275, 666, 831, 259, 251},
            {905, 421, 0, 286, 136, 338, 764, 249, 881, 508, 902, 798},
            {911, 824, 286, 0, 924, 282, 815, 40, 242, 571, 448, 886},
            {236, 270, 136, 924, 0, 88, 521, 140, 345, 799, 544, 295},
            {173, 350, 338, 282, 88, 0, 584, 254, 61, 76, 931, 870},
            {549, 79, 764, 815, 521, 584, 0, 353, 795, 547, 213, 198},
            {85, 275, 249, 40, 140, 254, 353, 0, 181, 682, 427, 539},
            {506, 666, 881, 242, 345, 61, 795, 181, 0, 618, 775, 521},
            {972, 831, 508, 571, 799, 76, 547, 682, 618, 0, 734, 462},
            {911, 259, 902, 448, 544, 931, 213, 427, 775, 734, 0, 162},
            {681, 251, 798, 886, 295, 870, 198, 539, 521, 462, 162, 0}
        };

        HeatMap heatMap = new HeatMap(data);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(heatMap);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}


Resultado:


sábado, 18 de mayo de 2024

Cálculo de la distancia entre dos puntos en un espacio de 6 dimensiones.

La distancia euclidiana es una medida de la longitud del segmento de línea recta que conecta dos puntos en un espacio n-dimensional.
En este caso, los dos puntos están representados por los vectores a1​ y b1​. Como es un espacio en 6D cada vector constará de 6 coordenadas cartesianas.



Código Java (CalculoDistanciaEuclideana.java):

package calculodistanciaeuclideana;

public class CalculoDistanciaEuclideana {

    public static void main(String[] args) {
        // Representación de dos puntos (a1, b1) en un espacio de 6 dimensiones (en coordenadas cartesianas)
        double[] a1 = {88, 74, 33, 29, 47, 58};
        double[] b1 = {29, 56, 13, 68, 11, 87};
        double distance = calculodistanciaeuclideana(a1, b1);
        System.out.println("La distancia entre a1 y b1 es: " + distance);
    }

    public static double calculodistanciaeuclideana(double[] a1, double[] b1) {        
        double sum = 0.0;
        for (int i = 0; i < a1.length; i++) {
            sum += Math.pow(b1[i] - a1[i], 2);
        }
        return Math.sqrt(sum);
    }
}

 

Resultado: 

run:
La distancia entre a1 y b1 es: 88.67355862939075
BUILD SUCCESSFUL (total time: 0 seconds)

sábado, 15 de abril de 2023

Juegos III.1. Generador de Sudokus aleatorios.

En esta versión se añade formato al tablero de juego mediante caracteres ASCII.


Código Java (SudokuGenerator.java):

package sudokugenerator;

import java.util.Random;

public class SudokuGenerator {

    private static final int BOARD_SIZE = 9;
    private static final int SUB_GRID_SIZE = 3;
    private static final int NUM_REMOVES = 20;

    public static void main(String[] args) {
        int[][] board = generateSudoku();
        printBoard(board);
    }

    public static int[][] generateSudoku() {
        int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
        populateBoard(board);
        removeCells(board);
        return board;
    }

    private static void populateBoard(int[][] board) {
        if (!solve(board, 0, 0)) {
            throw new IllegalStateException("No se pudo generar un sudoku válido.");
        }
    }

    private static boolean solve(int[][] board, int row, int col) {
        if (col == BOARD_SIZE) {
            col = 0;
            row++;
            if (row == BOARD_SIZE) {
                return true;
            }
        }

        if (board[row][col] != 0) {
            return solve(board, row, col + 1);
        }

        Random rand = new Random();
        for (int num : rand.ints(1, BOARD_SIZE + 1).distinct().limit(BOARD_SIZE).toArray()) {
            if (isValid(board, row, col, num)) {
                board[row][col] = num;
                if (solve(board, row, col + 1)) {
                    return true;
                }
            }
        }

        board[row][col] = 0;
        return false;
    }

    private static boolean isValid(int[][] board, int row, int col, int num) {
        for (int i = 0; i < BOARD_SIZE; i++) {
            if (board[row][i] == num || board[i][col] == num) {
                return false;
            }
        }

        int r = row - row % SUB_GRID_SIZE;
        int c = col - col % SUB_GRID_SIZE;
        for (int i = r; i < r + SUB_GRID_SIZE; i++) {
            for (int j = c; j < c + SUB_GRID_SIZE; j++) {
                if (board[i][j] == num) {
                    return false;
                }
            }
        }

        return true;
    }

    private static void removeCells(int[][] board) {
        Random rand = new Random();
        for (int i = 0; i < NUM_REMOVES; i++) {
            int row = rand.nextInt(BOARD_SIZE);
            int col = rand.nextInt(BOARD_SIZE);
            board[row][col] = 0;
        }
    }

    private static void printBoard(int[][] board) {
        System.out.println("+-------+-------+-------+");
        for (int i = 0; i < BOARD_SIZE; i++) {
            System.out.print("| ");
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (board[i][j] == 0) {
                    System.out.print("▓ ");
                } else {
                    System.out.print(board[i][j] + " ");
                }
                if (j % 3 == 2) {
                    System.out.print("| ");
                }
            }
            System.out.println();
            if (i % 3 == 2) {
                System.out.println("+-------+-------+-------+");
            }
        }
    }
}


Resultado:

run:
+-------+-------+-------+
| ▓ 6 3 | 9 7 8 | 1 2 5 |
| 9 7 8 | 5 ▓ ▓ | 6 3 4 |
| 5 2 1 | 4 6 3 | 8 ▓ 9 |
+-------+-------+-------+
| 3 5 9 | 7 2 ▓ | ▓ 1 ▓ |
| 2 1 ▓ | 8 ▓ 4 | 3 9 ▓ |
| ▓ ▓ 4 | 1 3 9 | ▓ 5 7 |
+-------+-------+-------+
| 8 ▓ 2 | 3 4 7 | 5 6 1 |
| 1 4 6 | 2 9 ▓ | 7 ▓ 3 |
| 7 ▓ 5 | ▓ 8 1 | ▓ 4 2 |
+-------+-------+-------+
BUILD SUCCESSFUL (total time: 0 seconds)

Juegos III. Generador de Sudokus aleatorios.

Este generador crea un tablero de Sudoku completamente resuelto utilizando backtracking y luego elimina un número específico de celdas (en este caso 20) para crear el puzzle. Puedes ajustar el número de celdas eliminadas (NUM_REMOVES) para controlar la dificultad del sudoku generado.


Código Java (SudokuGenerator.java):

package sudokugenerator;

import java.util.Random;

public class SudokuGenerator {

    private static final int BOARD_SIZE = 9;
    private static final int SUB_GRID_SIZE = 3;
    private static final int NUM_REMOVES = 20;

    public static void main(String[] args) {
        int[][] board = generateSudoku();
        printBoard(board);
    }

    public static int[][] generateSudoku() {
        int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
        populateBoard(board);
        removeCells(board);
        return board;
    }

    private static void populateBoard(int[][] board) {
        if (!solve(board, 0, 0)) {
            throw new IllegalStateException("No se pudo generar un sudoku válido.");
        }
    }

    private static boolean solve(int[][] board, int row, int col) {
        if (col == BOARD_SIZE) {
            col = 0;
            row++;
            if (row == BOARD_SIZE) {
                return true;
            }
        }

        if (board[row][col] != 0) {
            return solve(board, row, col + 1);
        }

        Random rand = new Random();
        for (int num : rand.ints(1, BOARD_SIZE + 1).distinct().limit(BOARD_SIZE).toArray()) {
            if (isValid(board, row, col, num)) {
                board[row][col] = num;
                if (solve(board, row, col + 1)) {
                    return true;
                }
            }
        }

        board[row][col] = 0;
        return false;
    }

    private static boolean isValid(int[][] board, int row, int col, int num) {
        for (int i = 0; i < BOARD_SIZE; i++) {
            if (board[row][i] == num || board[i][col] == num) {
                return false;
            }
        }

        int r = row - row % SUB_GRID_SIZE;
        int c = col - col % SUB_GRID_SIZE;
        for (int i = r; i < r + SUB_GRID_SIZE; i++) {
            for (int j = c; j < c + SUB_GRID_SIZE; j++) {
                if (board[i][j] == num) {
                    return false;
                }
            }
        }

        return true;
    }

    private static void removeCells(int[][] board) {
        Random rand = new Random();
        for (int i = 0; i < NUM_REMOVES; i++) {
            int row = rand.nextInt(BOARD_SIZE);
            int col = rand.nextInt(BOARD_SIZE);
            board[row][col] = 0;
        }
    }

    private static void printBoard(int[][] board) {
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                System.out.print(board[i][j] + " ");
            }
            System.out.println();
        }
    }
}


Resultado:

2 7 9 4 3 8 1 5 0
3 4 1 0 7 6 2 8 0
6 8 5 2 1 0 7 3 4
9 0 8 3 0 7 0 6 0
4 1 3 9 6 0 8 7 2
5 0 0 1 0 2 4 9 3
7 9 2 6 0 1 3 4 0
0 3 6 7 2 4 9 1 5
1 5 4 0 9 3 0 2 7

viernes, 14 de abril de 2023

Juegos II. Piedra papel tijeras.

Es un juego de manos en el que se selecciona entre piedra, papel o tijeras, con el objetivo de vencer al oponente. La piedra vence a las tijeras, las tijeras vencen al papel y el papel vence a la piedra.


Código Java (PiedraPapelTijeras.java):

import java.util.Random;
import java.util.Random;
import java.util.Scanner;

public class PiedraPapelTijeras {

    public static void main(String[] args) {
        String[] opciones = {"piedra", "papel", "tijeras"};
        Scanner scanner = new Scanner(System.in);
        Random random = new Random();
        int puntajeJugador = 0;
        int puntajeComputadora = 0;
        String respuesta;
        do {
            String computadora = opciones[random.nextInt(opciones.length)];
            System.out.print("Elige Piedra, Papel o Tijeras: ");
            String jugador = scanner.nextLine().toLowerCase();
            System.out.println("Jugador: " + jugador);
            System.out.println("Computadora: " + computadora);
            if (jugador.equals(computadora)) {
                System.out.println("Empate.");
            } else if ((jugador.equals("piedra") && computadora.equals("tijeras"))
                    || (jugador.equals("papel") && computadora.equals("piedra"))
                    || (jugador.equals("tijeras") && computadora.equals("papel"))) {
                System.out.println("Ganaste.");
                puntajeJugador++;
            } else {
                System.out.println("Perdiste.");
                puntajeComputadora++;
            }
            System.out.println("Puntuacion: Jugador " + puntajeJugador + ", Computadora " + puntajeComputadora);
            System.out.print("Quieres jugar de nuevo? (s/n): ");
            respuesta = scanner.nextLine();
        } while (respuesta.equalsIgnoreCase("s"));
    }
}


Resultado:

Elige Piedra, Papel o Tijeras: piedra
Jugador: piedra
Computadora: tijeras
Ganaste.
Puntuacion: Jugador 1, Computadora 0
Quieres jugar de nuevo? (s/n): s
Elige Piedra, Papel o Tijeras: tijeras
Jugador: tijeras
Computadora: papel
Ganaste.
Puntuacion: Jugador 2, Computadora 0
Quieres jugar de nuevo? (s/n): s
Elige Piedra, Papel o Tijeras: papel
Jugador: papel
Computadora: papel
Empate.
Puntuacion: Jugador 2, Computadora 0
Quieres jugar de nuevo? (s/n): s
Elige Piedra, Papel o Tijeras: tijeras
Jugador: tijeras
Computadora: piedra
Perdiste.
Puntuacion: Jugador 2, Computadora 1
Quieres jugar de nuevo? (s/n): n

Juegos I. Guess the number.

En este ejemplo, el programa genera un número aleatorio entre 1 y 100 y le da al usuario un máximo de 10 intentos para adivinar el número correcto. Cada vez que el usuario ingresa un número, el programa verifica si es mayor o menor que el número aleatorio y proporciona una pista.


Código Java (AdivinaNumero.java):

import java.util.Random;
import java.util.Scanner;

public class AdivinaNumero {
    public static void main(String[] args) {
        Random rand = new Random();
        int numeroAleatorio = rand.nextInt(100) + 1; // Genera un numero aleatorio entre 1 y 100
        Scanner sc = new Scanner(System.in);
        int intentos = 0;
        int numeroIngresado = 0;
        while (intentos < 10) { // El usuario tiene un maximo de 10 intentos
            System.out.print("Adivina el numero (entre 1 y 100): ");
            numeroIngresado = sc.nextInt();
            intentos++;
            if (numeroIngresado == numeroAleatorio) { // Si el usuario adivina el numero, sale del loop
                System.out.println("Felicidades! Adivinaste el numero en " + intentos + " intentos.");
                break;
            } else if (numeroIngresado < numeroAleatorio) {
                System.out.println("El numero es mayor.");
            } else {
                System.out.println("El numero es menor.");
            }
        }
        if (intentos == 10) { // Si el usuario agota sus 10 intentos, muestra el numero aleatorio
            System.out.println("Lo siento, agotaste tus intentos. El numero era " + numeroAleatorio + ".");
        }
    }
}


Resultado:

Adivina el numero (entre 1 y 100): 50
El numero es menor.
Adivina el numero (entre 1 y 100): 25
El numero es mayor.
Adivina el numero (entre 1 y 100): 42
El numero es menor.
Adivina el numero (entre 1 y 100): 35
Felicidades! Adivinaste el numero en 4 intentos.

lunes, 27 de marzo de 2023

El autómata de clase 4. Patrón 110.

El autómata celular unidimensional basado en la regla 110 de Stephen Wolfram, es un sistema de evolución discreto que sigue reglas simples para generar patrones complejos a partir de una serie inicial de células.

El ejemplo de autómata de clase 4 aquí descrito, produce patrones complejos y no periódicos que pueden ser difíciles de predecir. Estos patrones pueden tener aplicaciones en la generación de números pseudoaleatorios, criptografía y en simulación de sistemas complejos.


Código Java (Regla110.java):

public class Regla110 {
    public static void main(String[] args) {
        int[] cells = new int[64];
        cells[cells.length / 2] = 1;
        int[] newCells = new int[cells.length];

        for (int t = 0; t < 32; t++) {
            printCells(cells);

            for (int i = 1; i < cells.length - 1; i++) {
                int left = cells[i - 1];
                int center = cells[i];
                int right = cells[i + 1];
                newCells[i] = applyRule110(left, center, right);
            }

            System.arraycopy(newCells, 0, cells, 0, cells.length);
        }
    }

    private static void printCells(int[] cells) {
        for (int cell : cells) {
            System.out.print(cell == 0 ? "." : "┼");
        }
        System.out.println();
    }

    private static int applyRule110(int left, int center, int right) {
        int rule = (left << 2) | (center << 1) | right;
        int rule110 = 0b01110110;
        return (rule110 >> rule) & 1;
    }
}


Resultado:

run:
................................┼...............................
...............................┼┼┼..............................
..............................┼..┼┼.............................
.............................┼┼┼┼.┼┼............................
............................┼...┼┼.┼┼...........................
...........................┼┼┼.┼.┼┼.┼┼..........................
..........................┼..┼┼┼┼.┼┼.┼┼.........................
.........................┼┼┼┼...┼┼.┼┼.┼┼........................
........................┼...┼┼.┼.┼┼.┼┼.┼┼.......................
.......................┼┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼......................
......................┼..┼┼┼┼...┼┼.┼┼.┼┼.┼┼.....................
.....................┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼....................
....................┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼...................
...................┼┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼..................
..................┼..┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼.┼┼.................
.................┼┼┼┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼.┼┼................
................┼...┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼.┼┼...............
...............┼┼┼.┼.┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼..............
..............┼..┼┼┼┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.............
.............┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼............
............┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼...........
...........┼┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼..........
..........┼..┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.........
.........┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼........
........┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.......
.......┼┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼......
......┼..┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.....
.....┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼....
....┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼...
...┼┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼..
..┼..┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.
.┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼.┼┼┼┼...┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼┼.┼.
BUILD SUCCESSFUL (total time: 0 seconds)

martes, 14 de febrero de 2023

Espirales. Graficar Espiral de Fermat.

La espiral de Fermat es una curva logarítmica que se describe mediante una ecuación polar. Esta espiral se caracteriza por tener radios que se expanden logarítmicamente con respecto al ángulo polar. La ecuación de la espiral de Fermat es:

r = a * t^(1/n)

r: Distancia del origen a un punto en la espiral.
a: Constante positiva. Controla la tasa de expansión de los radios en la espiral.
t: Ángulo polar.
n: Exponente de la constante. Determina el grado de curvatura de la espiral y cómo se relaciona con el ángulo polar.


Código Java (FermatSpiral.java):

package fermatspiral;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class FermatSpiral extends JPanel {

    private static final long serialVersionUID = 1L;
    private static final int MAX_ITER = 512;
    private static final double SCALE = 80;
    private static final double A = 1;
    private static final int N = 3;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.translate(getWidth() / 2, getHeight() / 2);
        float lineWidth = 0.1f;
        double theta = 0;
        double r;
        g2d.setColor(Color.BLUE);
        double x1 = 0, y1 = 0, x2, y2;
        for (int i = 0; i < MAX_ITER; i++) {
            r = A * Math.pow(theta, 1.0 / N);
            x2 = SCALE * r * Math.cos(theta);
            y2 = SCALE * r * Math.sin(theta);
            g2d.setStroke(new BasicStroke(lineWidth));
            g2d.draw(new Line2D.Double(x1, y1, x2, y2));
            theta += 0.1;
            lineWidth += 0.01;
            x1 = x2;
            y1 = y2;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Spiral Fermat");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new FermatSpiral());
        frame.setSize(new Dimension(800, 800));
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
}


Resultado:


domingo, 12 de febrero de 2023

Espirales. Graficar Espiral de Arquímedes.

La espiral de Arquímedes es una curva matemática que se genera mediante la rotación de una recta alrededor de un punto fijo.


Código Java (ArquimedesSpiral.java):

package arquimedesspiral;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class ArquimedesSpiral extends JComponent {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        int width = getWidth();
        int height = getHeight();

        g2d.translate(width / 2, height / 2);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        double t = 0.1;
        double a = 5;

        int x1 = 0;
        int y1 = 0;

        g2d.setColor(Color.BLUE);

        for (int i = 0; i <= 500; i++) {
            int x2 = (int) (a * t * Math.cos(t));
            int y2 = (int) (a * t * Math.sin(t));

            g2d.setStroke(new BasicStroke((float) i / 100));
            g2d.drawLine(x1, y1, x2, y2);

            x1 = x2;
            y1 = y2;

            t += 0.1;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new ArquimedesSpiral());
        frame.setSize(800, 800);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

}


Resultado:


Espirales. Graficar Espiral Logarítmica.

La espiral logarítmica es una curva matemática que se genera a partir de la relación logarítmica entre su distancia radial y su ángulo polar.


Código java (LogarithmicSpiral.java):

package logarithmicspiral;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class LogarithmicSpiral extends JComponent {

@Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;

    int width = getWidth();
    int height = getHeight();

    g2d.translate(width / 2, height / 2);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    double theta = 0.5;
    double a = 1;
    double b = 0.12;

    int x1 = 0;
    int y1 = 0;

    g2d.setColor(Color.BLUE);

    for (int i = 0; i <= 500; i++) {
      double r = a * Math.exp(b * theta);
      int x2 = (int) (r * Math.cos(theta));
      int y2 = (int) (r * Math.sin(theta));

      g2d.setStroke(new BasicStroke((float) i / 100));
      g2d.drawLine(x1, y1, x2, y2);

      x1 = x2;
      y1 = y2;

      theta += 0.1;
    }
  }

  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new LogarithmicSpiral());
    frame.setSize(800, 800);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

}


Resultado:



sábado, 28 de enero de 2023

Permutaciones. Algoritmo lexicográfico.

El algoritmo lexicográfico es un algoritmo de generación de permutaciones que genera todas las permutaciones de un conjunto de elementos en orden lexicográfico. Es similar al algoritmo de Heap, pero en lugar de usar una estructura de datos específica, utiliza una técnica de backtracking para generar las permutaciones. Tiene una complejidad temporal de O(n! * n).


Código Java (LexicographicPermutation.java):

import java.util.Arrays;

public class LexicographicPermutation {
    private static int[] elements = {1, 2, 3, 4, 5, 6, 7, 8};
    private static boolean[] used = new boolean[elements.length];

    public static void main(String[] args) {
        lexicographicPermutation(new int[elements.length], 0);
    }

    private static void lexicographicPermutation(int[] permutation, int index) {
        if (index == elements.length) {
            System.out.println(Arrays.toString(permutation));
            return;
        }

        for (int i = 0; i < elements.length; i++) {
            if (!used[i]) {
                used[i] = true;
                permutation[index] = elements[i];
                lexicographicPermutation(permutation, index + 1);
                used[i] = false;
            }
        }
    }
}


Resultado:

[1, 2, 3, 4]
[1, 2, 4, 3]
[1, 3, 2, 4]
[1, 3, 4, 2]
[1, 4, 2, 3]
[1, 4, 3, 2]
[2, 1, 3, 4]
[2, 1, 4, 3]
[2, 3, 1, 4]
[2, 3, 4, 1]
[2, 4, 1, 3]
[2, 4, 3, 1]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 2, 1, 4]
[3, 2, 4, 1]
[3, 4, 1, 2]
[3, 4, 2, 1]
[4, 1, 2, 3]
[4, 1, 3, 2]
[4, 2, 1, 3]
[4, 2, 3, 1]
[4, 3, 1, 2]
[4, 3, 2, 1]

Permutaciones. Algoritmo de Heap.

El algoritmo de Heap es un algoritmo de generación de permutaciones que utiliza una estructura de datos conocida como heap. La idea es generar todas las permutaciones de un conjunto de elementos en orden lexicográfico. Tiene una complejidad temporal de O(n!).


Código Java (HeapPermutation.java):

import java.util.Arrays;

public class HeapPermutation {
    private static int[] elements = {1, 2, 3, 4};

    public static void main(String[] args) {
        heapPermutation(elements.length);
    }

    private static void heapPermutation(int size) {
        if (size == 1) {
            System.out.println(Arrays.toString(elements));
            return;
        }

        for (int i = 0; i < size; i++) {
            heapPermutation(size - 1);

            if (size % 2 == 1) {
                int temp = elements[0];
                elements[0] = elements[size - 1];
                elements[size - 1] = temp;
            } else {
                int temp = elements[i];
                elements[i] = elements[size - 1];
                elements[size - 1] = temp;
            }
        }
    }
}


Resultado:

[1, 2, 3, 4]
[2, 1, 3, 4]
[3, 1, 2, 4]
[1, 3, 2, 4]
[2, 3, 1, 4]
[3, 2, 1, 4]
[4, 2, 3, 1]
[2, 4, 3, 1]
[3, 4, 2, 1]
[4, 3, 2, 1]
[2, 3, 4, 1]
[3, 2, 4, 1]
[4, 1, 3, 2]
[1, 4, 3, 2]
[3, 4, 1, 2]
[4, 3, 1, 2]
[1, 3, 4, 2]
[3, 1, 4, 2]
[4, 1, 2, 3]
[1, 4, 2, 3]
[2, 4, 1, 3]
[4, 2, 1, 3]
[1, 2, 4, 3]
[2, 1, 4, 3]


miércoles, 28 de diciembre de 2022

Conversión de Infijo a Postfijo usando pilas (v.4). Mejorar formato de entrada.

Se incorpora mejoras en la función de limpieza y formateo que permite ajustar la calidad y la precisión de la expresión de entrada, eliminando cualquier elemento innecesario y corrigiendo posibles errores de formateo.


Código Java (InfijoPostfijo.java):

package infijopostfijo;

import java.util.Scanner;
import java.util.Stack;

public class InfijoPostfijo {

    public static void main(String[] args) {

        // Declaración de las pilas
        Stack<String> E = new Stack<>(); // Pila entrada
        Stack<String> P = new Stack<>(); // Pila temporal para operadores
        Stack<String> S = new Stack<>(); // Pila salida

        // Entrada de datos
        System.out.println("> Ingresa expresión algebraica a convertir:");
        Scanner leer = new Scanner(System.in);

        // Pasar expresión algebraica a la Pila de entrada (E)
        String[] arrayInfix = formato(leer.nextLine()).split(" ");
        for (int i = arrayInfix.length - 1; i >= 0; i--) {
            E.push(arrayInfix[i]);
        }

        // Conversor Infijo a Postfijo
        while (!E.isEmpty()) {
            switch (prioridad(E.peek())) {
                case 1 ->
                    P.push(E.pop());
                case 2 -> {
                    while (!P.peek().equals("(")) {
                        S.push(P.pop());
                    }
                    P.pop();
                    E.pop();
                }
                case 3, 4 -> {
                    while (prioridad(P.peek()) >= prioridad(E.peek())) {
                        S.push(P.pop());
                    }
                    P.push(E.pop());
                }
                case 5 ->
                    P.push(E.pop());
                default ->
                    S.push(E.pop());
            }
        }

        // Mostrar resultado:
        System.out.println("> Expresión en notación Postfija:\n" + S.toString().replaceAll("[\\]\\[,]", ""));

    }

    // Prioridad de los operadores
    private static int prioridad(String op) {
        return switch (op) {
            case "^" -> 5;
            case "*", "/" -> 4;
            case "+", "-" -> 3;
            case ")" -> 2;
            case "(" -> 1;
            default -> 99;
        };
    }

    // Formato expresión algebraica
    private static String formato(String expr) {
        expr = expr.trim();
        expr = expr.charAt(0) == '-' ? "0-" + expr.substring(1) : expr;
        expr = expr.replaceAll("\\(-(\\d)", "(0-$1");
        expr = expr.replaceAll("(\\d)\\(", "$1*(");
        expr = expr.replaceAll("\\)(\\d)", ")*$1");
        expr = expr.replaceAll("([\\+|\\-|\\*|\\/|\\(|\\)|\\^|])", " $1 ");
        expr = expr.replaceAll("\\s+", " ");
        return "( " + expr + " )";
    }

}


Resultado:

run:
> Ingresa expresión algebraica a convertir:
-4(56-3+5)/2-(45+34)+(-23*(-52)6+2)-1   
> Expresión en notación Postfija:
0 4 56 3 - 5 + * 2 / - 45 34 + - 0 23 0 52 - * 6 * - 2 + + 1 -
BUILD SUCCESSFUL (total time: 2 seconds)

Con la tecnología de Blogger.