Caracteristicas del Juego:
. Objetivo: Calcular un número específico (el objetivo) usando los números disponibles y las operaciones aritméticas básicas.
. Números Disponibles: Se generan seis números aleatorios que pueden usarse cada uno una sola vez en los cálculos.
. Operaciones Permitidas: Suma, resta, multiplicación y división(siempre que el resultado sea un número entero).
. Uso de Números: Cada número puede usarse una sola vez.
. Resultado Entero: Todas las operaciones deben producir resultados enteros.
El algoritmo explora exhaustivamente todas las combinaciones posibles de los seis números generados aleatoriamente y las operaciones básicas, buscando alcanzar el número objetivo o el más cercano posible. Devuelve el mejor resultado encontrado junto con la expresión utilizada para llegar a él.
Estructura del código Approximate:
approximate (paquete)
│
└── Approximate (clase pública)
│
├── static fields (campos estáticos)
│ ├── OPERADORES (array de caracteres)
│ ├── mejorResultado (entero)
│ ├── mejorExpresion (cadena)
│ └── OBJETIVO_NO_ALCANZADO (constante entera)
│
├── main() (método principal)
│
└── private static methods (métodos privados estáticos)
├── generarCombinaciones()
├── generarPermutaciones()
├── generarOperaciones()
├── evaluarExpresion()
├── construirExpresion()
├── evaluarExpresionAritmetica()
├── tokenizarExpresion()
└── evaluarTokens()
Código Java (Approximate.java):
package approximate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class Approximate {
private static final char[] OPERADORES = {'+', '-', '*', '/'};
private static int mejorResultado;
private static String mejorExpresion;
private static final int OBJETIVO_NO_ALCANZADO = Integer.MAX_VALUE;
public static void main(String[] args) {
Random random = new Random();
int objetivo = random.nextInt(999) + 1;
Set<Integer> numerosSet = new HashSet<>();
while (numerosSet.size() < 6) {
int nuevoNumero = random.nextInt(100) + 1;
if (nuevoNumero != objetivo) {
numerosSet.add(nuevoNumero);
}
}
Integer[] numeros = numerosSet.toArray(new Integer[0]);
System.out.println("Número objetivo: " + objetivo);
System.out.println("Números disponibles: " + Arrays.toString(numeros));
mejorResultado = OBJETIVO_NO_ALCANZADO;
mejorExpresion = "";
generarCombinaciones(numeros, objetivo);
if (mejorResultado != OBJETIVO_NO_ALCANZADO) {
System.out.println("Mejor aproximación: " + mejorResultado);
System.out.println("Expresión: " + mejorExpresion);
} else {
System.out.println("No se encontró una solución válida.");
}
}
private static void generarCombinaciones(Integer[] numeros, int objetivo) {
for (int i = 1; i <= numeros.length; i++) {
generarPermutaciones(Arrays.asList(numeros), new ArrayList<>(), i, objetivo);
}
}
private static void generarPermutaciones(List<Integer> numeros, List<Integer> permutacion, int longitud, int objetivo) {
if (permutacion.size() == longitud) {
generarOperaciones(permutacion, new ArrayList<>(), objetivo);
return;
}
for (int i = 0; i < numeros.size(); i++) {
List<Integer> nuevaPermutacion = new ArrayList<>(permutacion);
nuevaPermutacion.add(numeros.get(i));
List<Integer> nuevosNumeros = new ArrayList<>(numeros);
nuevosNumeros.remove(i);
generarPermutaciones(nuevosNumeros, nuevaPermutacion, longitud, objetivo);
}
}
private static void generarOperaciones(List<Integer> numeros, List<Character> operadores, int objetivo) {
if (operadores.size() == numeros.size() - 1) {
evaluarExpresion(numeros, operadores, objetivo);
return;
}
for (char operador : OPERADORES) {
List<Character> nuevosOperadores = new ArrayList<>(operadores);
nuevosOperadores.add(operador);
generarOperaciones(numeros, nuevosOperadores, objetivo);
}
}
private static void evaluarExpresion(List<Integer> numeros, List<Character> operadores, int objetivo) {
String expresion = construirExpresion(numeros, operadores);
try {
int resultado = evaluarExpresionAritmetica(expresion);
int diferencia = Math.abs(resultado - objetivo);
if (diferencia < Math.abs(mejorResultado - objetivo)) {
mejorResultado = resultado;
mejorExpresion = expresion;
}
} catch (ArithmeticException e) {
// Ignorar divisiones inválidas
}
}
private static String construirExpresion(List<Integer> numeros, List<Character> operadores) {
StringBuilder expresion = new StringBuilder();
expresion.append(numeros.get(0));
for (int i = 0; i < operadores.size(); i++) {
expresion.append(operadores.get(i));
expresion.append(numeros.get(i + 1));
}
return expresion.toString();
}
private static int evaluarExpresionAritmetica(String expresion) {
List<String> tokens = tokenizarExpresion(expresion);
return evaluarTokens(tokens);
}
private static List<String> tokenizarExpresion(String expresion) {
List<String> tokens = new ArrayList<>();
StringBuilder numeroActual = new StringBuilder();
for (char c : expresion.toCharArray()) {
if (Character.isDigit(c)) {
numeroActual.append(c);
} else {
if (numeroActual.length() > 0) {
tokens.add(numeroActual.toString());
numeroActual = new StringBuilder();
}
tokens.add(String.valueOf(c));
}
}
if (numeroActual.length() > 0) {
tokens.add(numeroActual.toString());
}
return tokens;
}
private static int evaluarTokens(List<String> tokens) {
// Primero, evaluamos multiplicaciones y divisiones
for (int i = 1; i < tokens.size() - 1; i += 2) {
String operador = tokens.get(i);
if (operador.equals("*") || operador.equals("/")) {
int a = Integer.parseInt(tokens.get(i - 1));
int b = Integer.parseInt(tokens.get(i + 1));
int resultado;
if (operador.equals("*")) {
resultado = a * b;
} else {
if (b == 0 || a % b != 0) {
throw new ArithmeticException("División inválida");
}
resultado = a / b;
}
tokens.set(i - 1, String.valueOf(resultado));
tokens.remove(i);
tokens.remove(i);
i -= 2;
}
}
// Luego, evaluamos sumas y restas
int resultado = Integer.parseInt(tokens.get(0));
for (int i = 1; i < tokens.size(); i += 2) {
String operador = tokens.get(i);
int numero = Integer.parseInt(tokens.get(i + 1));
if (operador.equals("+")) {
resultado += numero;
} else if (operador.equals("-")) {
resultado -= numero;
}
}
return resultado;
}
}
Resultado:
run:
Número objetivo: 127
Números disponibles: [49, 4, 53, 7, 87, 76]
Mejor aproximación: 127
Expresión: 49*4+7-76
BUILD SUCCESSFUL (total time: 2 seconds)
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
-
►
2012
(38)
- ► septiembre (3)
-
►
2020
(12)
- ► septiembre (1)
-
▼
2024
(29)
-
▼
julio
(9)
- Generación de laberintos I.2. Algoritmo de Aldous-...
- Juegos IV. Tres en Raya.
- Juegos IV.2. Tres en Raya (GUI).
- Conversor matriz de distancias a coordenadas carte...
- Conversor matriz de distancias a coordenadas carte...
- Rotar matriz 90º. Uso de librería "Apache Commons ...
- Juegos V: Approximate: El Juego de Números y Opera...
- Juegos V.2: Approximate(GUI): El Juego de Números ...
- Juegos VI: The Marconix Codebreaker (Juego de Posi...
-
▼
julio
(9)
sábado, 20 de julio de 2024
Juegos V: Approximate: El Juego de Números y Operaciones.
Suscribirse a:
Enviar comentarios (Atom)
Con la tecnología de Blogger.
No hay comentarios:
Publicar un comentario