Universidad Mariano Gálvez de Guatemala Centro universitario de Villa Nueva Facultad de ingeniería en sistemas Asignatura: Programación III Catedrático: Ing. Santiago Mendez Semestre: Quinto Sección: B Tema de trabajo: Calculadora Binaria App Integrantes: Andrés Samayoa Penagos 5190-21-15972 Alba Azucena Hernández Velásquez 5190-21-5735 Yeimy Viviana Gudiel Moctezuma 5190-20-13061 Doris Yanet Joan Benito Meza 5190-21-19403 Roger Josue Fuentes Lima 5190-18-9576 Fecha de entrega: 26 de mayo de 2,023. Presentación Proyecto: Árbol binario app A continuación presentamos nuestro proyecto llamado árbol binario app, que es un sistema que registra una operación matemática ya que si designamos un valor, se desprenderá una serie de valores que van de derecha a izquierda. por lo que si nosotros realizamos una operación matemática en una calculadora, observamos en dicho código, procedemos a realizar dicha operación. A continuación mostraremos las plataformas utilizadas durante el desarrollo y muestra de nuestra aplicación. Android studio version 8.1.0.2 Apache netbeans studio version 14.1.2 Plataforma de aplicación en formato apk Hoy en día necesitamos realizar un sin fin de aplicaciones con el objetivo de desarrollar operaciones matemáticas que van desde una sencilla operación combinada de las operaciones básicas así como también el cálculo de funciones derivadas y/o integrales. Por ahora nos enfocaremos en el sistema de árboles de una operación matemática con el proceso de cálculo de valores que nos muestra un resultado que dirige dicho resultado que va de arriba hacia abajo. como se muestra, ya que el algoritmo desarrollado fue en base a que lea dichos valores tomados de la derecha hacia la izquierda: Fuentes de información ● Aho, Hopcroft, Ullman (1998). Estructuras de datos y Algoritmos. Addison-Wesley. ● Budd, Timoty (2002). Object-Oriented Programming. Third Edition. Addison-Wesley. ● Gilbert, Stephen y Mccarty, Bill (1997). Object-Oriented Programming in Java. Waite Group Press. Gilbert, Stephen y Mccarty, Bill (1998). ● Programación en Java2 . McGraw-Hill. Joyanes Luis y Zahonero Ignacio (2004). ● Addison-Wesley. Weiss, M.A (2000). Estructuras de datos en Java. ● Barnes, David (2000). Object-Oriented Programming in Java: An introduction. Prentice-Hall. ● Budd, Timoty (2002). Object-Oriented Programming. Third Edition. Addison-Wesley. ● Deitel, Harvey (2002). JAVA. How to program. Fourth edition, Prentice-Hall. ● Gilbert, Stephen y Mccarty, Bill (1997). Object-Oriented Programming in Java. Waite Group Press. Gilbert, Stephen y Mccarty, Bill (1998). Object-Oriented Design in Java. ● Core Java 2 Volumen I–Fundamentos. Pearson Educación. Hubbard, John R. (2001). Data Structures with Java. McGraw-Hill, Schaum´s OuTlines. Según lo establecido respecto a un árbol binario o Árbol AVL, se utiliza un árbol binario de búsqueda para almacenar datos organizados jerárquicamente. Sin embargo, en muchas ocasiones, las inserciones y eliminaciones de elementos en el árbol no ocurren en un orden predecible: es decir, los datos no están organizados jerárquicamente. En este capítulo se estudian tipos de árboles adicionales: los árboles equilibrados o árboles AVL, como también se les conoce, que ayudan eficientemente a resolver las situaciones citadas. El concepto de árbol equilibrado así como los algoritmos de manipulación constituyen el motivo central de este capítulo. Los métodos que describen este tipo de árboles fueron descritos en 1962 por los matemáticos rusos G. M. Adelson-Velskii y E. M. Landis. La eficiencia de una búsqueda en un árbol binario ordenado varía entre O(n) y O(log(n)), dependiendo de la estructura que presente el árbol. Si los elementos se añaden en el árbol mediante el algoritmo de inserción expuesto en el capítulo anterior, la estructura resultante del árbol dependerá del orden en que sean añadidos. Así, si todos los elementos se insertan en orden creciente o decreciente, el árbol tendrá todas la ramas izquierda o derecha, respectivamente, vacías. En este caso, la búsqueda en dicho árbol será totalmente secuencial. ❖ Árboles binarios de búsqueda Los árboles binarios de búsqueda, al igual que los árboles binarios, tienen naturaleza recursiva y, en consecuencia, las operaciones sobre los árboles son recursivas, si bien siempre se tiene la opción de realizarlas de forma iterativa. Estas operaciones son: • Búsqueda de un nodo. Devuelve la referencia al nodo del árbol o null. • Inserción de un nodo. Crea un nodo con su dato asociado y lo añade, en orden, al árbol. • Borrado de un nodo. Busca el nodo del árbol que contiene un dato y lo quita. El árbol debe seguir siendo de búsqueda. • Recorrido de un árbol. Los mismos recorridos de un árbol binario preorden, inorden y postorden. Documentación del programa En el proceso de desarrollo de nuestra aplicación tomamos como idea el proceso que llevará a cabo nuestro software fue que el sistema de reconocimiento de patrones numéricos como lo son la lectura de un número que envía la información hacia otro punto o nodo que formará un enlace entre los valores ingresados como lo también lo son los valores tales como variables en el código establecido: if (valor.getDato() == null) { return 0; }else if(valor.getDato().equals("+")) { resultado=iz+de; } else if(valor.getDato().equals("-")) { resultado=iz-de; } else if(valor.getDato().equals("*")) { resultado=iz*de; } else if(valor.getDato().equals("/")) { resultado=iz/de; } else if(valor.getDato().equals("^")) { resultado= Math.pow(iz,de); } else { resultado=Double.valueOf(valor.getDato()); } return resultado; } Ya que si tomamos en cuenta cuando ingresamos los valores los resultados siempre toman en cuenta la representación gráfica como lo es la comprensión de los valores de una gráfica de nodos, es decir el cambio de posiciones como lo es el cambio de valores, el resultado no sería lo mismo, pero la lectura será como siempre los valores de la aplicación de movimiento Manual de Instalación Pre- requisitos ● ● ● Tener espacio de almacenamiento disponible. Obtener el JDK de la instalación de la aplicación “ProyectoProgra”. Tener permisos para instalar la aplicación. Instrucciones de instalación Para realizar la instalación de la App “ProyectoProgra” de manera correcta, realizar lo siguiente: 1. Instalar el archivo JDK de la Aplicación 2. Al finalizar la descarga del archivo APK proceder a abrirlo, al abrir el archivo se mostrará un mensaje de advertencia debido a que es una aplicación de remitente desconocido, solamente en esta ocasión presionar Abierto, ya que conocemos la procedencia del archivo. 3. Se muestra un mensaje indicando si se desea Instalar esta app, presionar Instalar. 4. Debido a que esta aplicación no se encuentra en la PlayStore se muestra el siguiente mensaje de seguridad indicando que la aplicación se bloqueo, presionar “Más Detalles”. 5. Proceder a Presionar la opción “Instalar de todas formas”. 6. Presionar el botón “Entendido”. 7. Se muestra un mensaje indicando que la app “ProyecoProgra”, se instaló, presionar el botón “ABRIR”. 8. Verificar que la aplicación se inició correctamente. 9. Validar que la aplicación se muestra correctamente en la pantalla principal del móvil. 10. Para Abrir la aplicación desde la pantalla principal, proceder a dar clic sobre el icono de la aplicación ProyectoProgra, y verificar que la aplicación se inicia correctamente. Manual del Usuario Estimado usuario, para poder validar el procedimiento de la aplicación “ProyectoProgra” se debe realizar el siguiente procedimiento: Proceder a abrir la aplicación “ProyectoProgra”, dando clic sobre el Icono. Se muestra una pantalla indicando que se debe ingresar una ecuación. En el apartado indicando que solamente se pueden ingresar números y símbolos. Proceder a ingresar una ecuación: 2/2+5*10+6 Presionar el botón “Calcular“ Se observa que se genera un recorrido de árbol de manera correcta clos datos de la ecuación ingresada Verificamos que al final de la pantalla se muestra la solución a la ecuación. Validar que el proceso de cálculo de la ecuación se realizó correctamente, ingresando los datos a la calculadora y validar que el resultado 57.0 es correcto. Código fuente: Componentes del Proyecto: 1. Nodo: Clase java que tiene la estructura de cada nodo del árbol, cuenta con la función que convierte al texto con una operación matemática en una pila de operaciones, primer paso para formar el árbol con la operación completa. 2. Árbol: Clase java que contiene el nodo raíz y el atributo nivel que sirve como la cantidad de espacios extra que se deben dar por nivel del árbol, en esta clase se encuentran también las funciones ProcesarEcuacionStack, que toma el stack dado por la clase Nodo y lo convierte en el árbol completo, evaluar, que recorre el árbol y lo evalúa, y mostrarArbolHorizontal, que grafica el árbol como texto. 3. FirstFragment: Clase java que funciona como el controlador de la vista fragment_first.xml. 4. MainActivity: Clase java que funciona como el controlador de la vista activity_main.xml. 5. activity_main: archivo xml que define la vista base que contiene el resto de los elementos. 6. content_main: archivo xml que define la vista base que contiene el encabezado del proyecto. 7. fragment_first: archivo xml que define la vista base que contiene los elementos interactivos. Cómo ejecutar el proyecto Para ejecutar el proyecto completo se debe de instalar la última versión de Android Studio que está disponible al momento (Android Studio Flamingo | 2022.2.1), luego se debe activar la virtualización desde la bios de la computadora y desactivar hyperv para poder emular el dispositivo Android de forma local, una vez seguidos estos pasos se debe extraer el proyecto, abrirlo con Android Studio y correr la aplicación, a continuación se adjunta el código de los componentes anteriormente descritos: Nodo.java: package com.example.proyectoprogra; import java.util.Stack; public class Nodo { String dato; Nodo izq; Nodo der; public Nodo(String dato) { this.dato = dato; this.izq = null; this.der = null; } public String getDato() { return dato; } public void setDato(String dato) { this.dato = dato; } public Nodo getIzq() { return izq; } public void setIzq(Nodo izq) { this.izq = izq; } public Nodo getDer() { return der; } public void setDer(Nodo der) { this.der = der; } public Stack<Nodo> ecuacionStack (String ecuacion) { Stack<Nodo> nodos = new Stack<Nodo>(); for(int i = 0; i < ecuacion.length(); i++) { char elemento = ecuacion.charAt(i); if (Character.isDigit(elemento)){ nodos.push(new Nodo(this.numeroCompleto(ecuacion, i))); i = this.numeroCompletoSaltos(ecuacion, i); } else if (String.valueOf(elemento).equals("-") && ((i-1) == -1 || !Character.isDigit(ecuacion.charAt((i-1))) )) { nodos.push(new Nodo(this.numeroCompleto(ecuacion, i))); i = this.numeroCompletoSaltos(ecuacion, i); } else { String num = this.numeroCompleto(ecuacion, i+1); Nodo nNodo = new Nodo(String.valueOf(elemento)); nNodo.setIzq(nodos.pop()); nNodo.setDer(new Nodo(num)); nodos.push(nNodo); } } nodos.pop(); Stack<Nodo> respuesta = new Stack<Nodo>(); while (!nodos.isEmpty()) respuesta.push((nodos.pop())); return respuesta; } public String numeroCompleto (String ecuacion, int i) { String num = String.valueOf(ecuacion.charAt(i)); int contDec = 0; while ((i+1) < ecuacion.length() && (Character.isDigit(ecuacion.charAt((i+1))) || String.valueOf(ecuacion.charAt((i+1))).equals(".")) ){ if (String.valueOf(ecuacion.charAt((i+1))).equals(".") && contDec > 0) { i++; continue; } else if(String.valueOf(ecuacion.charAt((i+1))).equals(".")) contDec++; i++; num += String.valueOf(ecuacion.charAt(i)); } return num; } public int numeroCompletoSaltos (String ecuacion, int i) { String num = String.valueOf(ecuacion.charAt(i)); int contDec = 0; while ((i+1) < ecuacion.length() && (Character.isDigit(ecuacion.charAt((i+1))) || String.valueOf(ecuacion.charAt((i+1))).equals(".")) ){ if (String.valueOf(ecuacion.charAt((i+1))).equals(".") && contDec > 0) { i++; continue; } else if(String.valueOf(ecuacion.charAt((i+1))).equals(".")) contDec++; i++; num += String.valueOf(ecuacion.charAt(i)); } return i; } public boolean validarLleno () { return this.der != null && this.izq != null; } } Arbol.java: package com.example.proyectoprogra; import java.util.ArrayList; import java.util.Stack; public class Arbol { Nodo raiz; int nivel = 1; public Arbol(Nodo raiz) { this.raiz = raiz; } public Arbol() { this.raiz = new Nodo(null); } public double evaluar(Nodo valor) { double resultado=0,iz = 0,de = 0; if (valor == null) { return 0; } iz = this.evaluar(valor.getIzq()); de = this.evaluar(valor.getDer()); if (valor.getDato() == null) { return 0; }else if(valor.getDato().equals("+")) { resultado=iz+de; } else if(valor.getDato().equals("-")) { resultado=iz-de; } else if(valor.getDato().equals("*")) { resultado=iz*de; } else if(valor.getDato().equals("/")) { resultado=iz/de; } else if(valor.getDato().equals("^")) { resultado= Math.pow(iz,de); } else { resultado=Double.valueOf(valor.getDato()); } return resultado; } public Arbol procesarEcuacion (Stack<Nodo> elementos) { Nodo acum = null; while (!elementos.isEmpty()) { Nodo elemento = elementos.pop(); if (this.esNumerico(elemento.getDato())){ acum = elemento; } else { elemento.setIzq(acum); elemento.setDer(elementos.pop()); acum = elemento; } } Arbol res = new Arbol(acum); return res; } public Arbol procesarEcuacionStack (Stack<Nodo> elementos) { Nodo acum = null; while (!elementos.isEmpty()) { Nodo elemento = elementos.pop(); if(acum == null){ acum = elemento; } else if ((elemento.dato.equals("+") || elemento.dato.equals("-")) && (acum.dato.equals("*") || acum.dato.equals("/")) ){ elemento.setIzq(acum); acum = elemento; } else if ((elemento.dato.equals("*") || elemento.dato.equals("/")) &&(acum.dato.equals("-") || acum.dato.equals("+")) ){ acum.setDer(elemento); } else { elemento.setIzq(acum); acum = elemento; } } Arbol res = new Arbol(acum); return res; } private boolean esNumerico(String str) { if (str == null) { return false; } try { double d = Double.parseDouble(str); } catch (NumberFormatException nfe) { return false; } return true; } public String mostrarArbolHorizontal(Nodo raiz, int espacio) { String tab = "\t"; String res = ""; if (raiz == null) return ""; espacio += nivel; res += mostrarArbolHorizontal(raiz.der, espacio); res += "\n"; for (int i = nivel; i < espacio; i++) res += tab; res += raiz.dato + "\n"; res += mostrarArbolHorizontal(raiz.izq, espacio); return res; } } FirstFragment.java: package com.example.proyectoprogra; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.navigation.fragment.NavHostFragment; import com.example.proyectoprogra.databinding.FragmentFirstBinding; import java.util.ArrayList; public class FirstFragment extends Fragment { private FragmentFirstBinding binding; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ){ binding = FragmentFirstBinding.inflate(inflater, container, false); return binding.getRoot(); } public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); binding.buttonFirst.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { View mainView = view.getRootView(); TextView resultTextView = mainView.findViewById(R.id.result); EditText ecuationText = mainView.findViewById(R.id.edit_ecuation); Arbol arbolEcuacion = new Arbol().procesarEcuacionStack(new Nodo(null).ecuacionStack(ecuationText.getText().toString())); String graph = arbolEcuacion.mostrarArbolHorizontal(arbolEcuacion.raiz, 0); Double respuesta = arbolEcuacion.evaluar(arbolEcuacion.raiz); resultTextView.setText(graph + "\n" +String.valueOf(respuesta)); } }); } @Override public void onDestroyView() { super.onDestroyView(); binding = null; } } MainActivity.java: package com.example.proyectoprogra; import android.os.Bundle; import com.google.android.material.snackbar.Snackbar; import androidx.appcompat.app.AppCompatActivity; import android.view.View; import androidx.core.view.WindowCompat; import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.example.proyectoprogra.databinding.ActivityMainBinding; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends AppCompatActivity { private AppBarConfiguration appBarConfiguration; private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build(); NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public boolean onSupportNavigateUp() { NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp(); } } activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".MainActivity"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" /> </com.google.android.material.appbar.AppBarLayout> <include layout="@layout/content_main" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> fragment_first.xml: <?xml version="1.0" encoding="utf-8"?> <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".FirstFragment"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp"> <Button android:id="@+id/button_first" android:layout_width="102dp" android:layout_height="48dp" android:layout_marginTop="32dp" android:text="Calcular" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.909" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/edit_ecuation" android:layout_width="200dp" android:layout_height="48dp" android:layout_marginTop="32dp" android:layout_marginEnd="12dp" android:layout_marginBottom="32dp" android:ems="10" android:inputType="text" android:digits="0,1,2,3,4,5,6,7,8,9,*,-,+,/,." android:hint="Solo numeros y caracteres de operacion" app:layout_constraintBottom_toTopOf="@+id/result" app:layout_constraintEnd_toStartOf="@+id/button_first" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/result" android:layout_width="340dp" android:layout_height="5000dp" android:layout_marginStart="21dp" android:layout_marginTop="24dp" android:layout_marginEnd="13dp" android:layout_marginBottom="16dp" android:textSize="26dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/button_first" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editTextText" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.core.widget.NestedScrollView> content_main.xml: <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <fragment android:id="@+id/nav_host_fragment_content_main" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/nav_graph" /> </androidx.constraintlayout.widget.ConstraintLayout>