Swift – Ejercicios resueltos (VII)

Diseñar un encriptador en modo consola utilizando una clase que tenga una propiedad para guardar la equivalencia entre las letras sin encriptar y las letras encriptadas. Para ello se deberá utilizar un array de estructuras. Además, dicha clase deberá contener una función para encriptar y otra para desencriptar. Se deberá diseñar una clase para probarlo. Las letras a encriptar y su equivalente se podrán añadir directamente desde código, y la cadena de texto a encriptar se deberá pedir por teclado, mostrando el resultado por pantalla.

...

Diseñar un encriptador en modo gráfico utilizando una clase que permita añadir las letras a encriptar y su equivalente, guardando dicho listado de manera persistente. Además, la aplicación deberá tener dos pantallas, de forma que en la primera se puedan encriptar o desencriptar expresiones según la equivalencia que se encuentre guardada en la aplicación. En la segunda pantalla se deberá poder modificar el listado de las letras que se deben encriptar, permitiendo añadir o quitar letras, volviendo a guardar en cada modificación dicho listado para que se mantenga entre las distintas ejecuciones de la aplicación. Para ello se puede utilizar un array de estructuras que se guardará utilizando la librería ‘Disk’ que se puede instalar utilizando ‘CocoaPods’.

...

Desarrollar una aplicación para mostrar el uso y la personalización de los diversos componentes de la interfaz gráfica de la librería UIKit. Se deberán consultar las diferentes opciones que nos proporciona la librería y escribir el código swift necesario para cambiar el valor de las propiedades más significativas de cada uno de los componentes y visualizar los resultados:

UILabel, UIButton, UIBarButtonItem, UITextField (isSecureTextEntry), UITextView, UIFont, UIAlertController (UIAlertAction, alerts, action sheets), UIPickerView, UIImageView (UIImage, transform, CGAffineTransform, scale, rotate, reverse), UIScrollView, UITableView (UITableViewCell, cells, sections), UIPageControl, UISlider, UISwitch, UIDatePicker, UIActivityIndicatorView, UISearchBar, UIWindow, UIToolBar, UIProgressView, UISegmentedControl, UIStepper, UNUserNotificationCenter, WKWebView, UIStackView, etc.

Añadir a la aplicación anterior un teclado sencillo para reproducir las notas musicales básicas utilizando el componente UIStackView y el reproductor AVAudioPlayer de la librería AVFoundation. Tenéis un ejemplo completo en el último post, y los archivos de audio con las notas musicales en Google Drive:

...

Añadir a la aplicación anterior un apartado para reproducir diversos sonidos similares a los de la aplicación Instant Buttons. Se podrán utilizar una serie de botones distribuidos en forma de rejilla utilizando el componente UIStackView:

...

Añadir a la aplicación anterior un apartado para obtener de un servicio web un listado con todos los ciclos formativos que se imparten en la Comunidad Valenciana. Dicho listado se deberá mostrar utilizando un componente UITableView, y se deberán poder realizar búsquedas utilizando un componente UISearchBar. Además, se deberá proporcionar un mecanismo para poder mostrar los nombres de los ciclos formativos en castellano o valenciano (se puede utilizar por ejemplo un «action sheet» o también se pueden añadir botones a la barra de navegación, o se puede colocar una barra con dos botones en la parte inferior de la pantalla, etc.). Podéis encontrar un ejemplo completo sobre cómo personalizar la barra de navegación aquí, o cómo crear una barra de botones aquí.





Añadir a la aplicación anterior un apartado para obtener de un servicio web un listado con todos los institutos públicos o concertados de la Comunidad Valenciana donde se imparten ciclos formativos. Dicho listado se deberá mostrar utilizando un componente UITableView, y se deberán poder realizar búsquedas utilizando un componente UISearchBar. Además, al pulsar sobre un instituto en particular, se deberá mostrar un alert con toda la información relativa a dicho instituto:





Realizar una modificación en el apartado anterior para que se muestren todos los ciclos del centro educativo que se seleccione, pasando a una vista nueva (se puede consultar este enlace para ver un ejemplo de cómo añadir y navegar a una nueva vista). Para ello en la nueva vista se deberá realizar una consulta diferente utilizando el «id» del instituto seleccionado. Por ejemplo, para obtener los ciclos formativos que se imparten en el instituto IES San Vicente:

... {"id":47,"denominacion":"IES San Vicente","codigo_centro":"03008423","provincia":"Alacant","localidad":"Sant Vicent Del Raspeig","tipo_via":"Cl","domicilio":"Lillo Juan","numero":"128","cp":"3690","telefono":"965936505","fax":"965936506","email":"[email protected]","director":"Joaquín Pastor Pina","firmaLocalidad":"S. Vicent Raspeig","gestion_id":10,"gestion":{"id":10,"descripcion":"Público"}} ...

https://fernandoruizrico.com:8001/api/getListadoCiclos/47
...

Añadir a la búsqueda de centros educativos un componente «UIPickerView» para poder elegir qué tipo de búsqueda se pretende realizar (por nombre del instituto, por provincia, por localidad, etc.). Se deberá utilizar una enumeración para establecer los campos por los que se puede filtrar:

...

Añadir a la aplicación anterior un apartado para obtener datos sobre el tiempo atmosférico de una ciudad concreta que se introducirá por teclado. Se pueden realizar consultas a la api «http://api.openweathermap.org». A continuación se muestra una llamada y el resultado que se obtiene en formato JSON. Para obtener dicho resultado sólo es necesario proporcionar un identificador de usuario (appid) que se obtiene gratuitamente en el siguiente enlace «https://openweathermap.org/appid«:

https://api.openweathermap.org/data/2.5/weather?q=Alicante&appid=xxxxxxxx&lang=es


{"coord":{"lon":-74.23,"lat":10.65},"weather":[{"id":800,"main":"Clear","description":"cielo claro","icon":"01n"}],"base":"stations","main":{"temp":300.82,"pressure":1009,"humidity":83,"temp_min":300.15,"temp_max":301.15},"visibility":10000,"wind":{"speed":3.6,"deg":10},"clouds":{"all":0},"dt":1562913434,"sys":{"type":1,"id":8584,"message":0.0066,"country":"CO","sunrise":1562928074,"sunset":1562973803},"timezone":-18000,"id":3682292,"name":"Alicante","cod":200}

Añadir a la aplicación anterior un apartado para crear una lista de tareas utilizando un componente UITableView y la librería Disk para guardar el listado en el móvil, permitiendo por lo menos añadir y borrar tareas:


	

Swift – Ejercicios resueltos (VI)

Utiliza el método filter para obtener todos los nombre de personas que se encuentran en un array llamado nombres y que comiencen por la letra «A»:

let nombres = ["Ana", "Juan", "Pepe", "Anastasio", "Ángel"]
let nombresConA = nombres.filter { $0.first == "A" || $0.first == "Á" }
print("Los siguientes nombres comienzan por 'A': \(nombresConA)")

Utilizando el método reduce, calcula la suma de todos los enteros de un array:

let numeros = [1, 2, 3, 4, 6, 8, 9, 3, 12, 11]
let suma = numeros.reduce(0, {$0 + $1})
print("La suma de los números \(numeros) es \(suma)")

Utilizando el método map calcula el número real que se obtiene al dividir el numerador entre el denominador de diversas fracciones que se encuentran almacenadas en un array de tuplas, e imprime el resultado:

let fracciones = [(1,2), (2, 3), (5, 1), (4, 7)]
let reales = fracciones.map {Double($0.0) / Double($0.1)}
print("De las fracciones \(fracciones) se obtienen los números reales \(reales)")

Utilizando el método sorted, ordena ascendentemente todos los enteros de un array:

let numeros = [1, 6, 3, 34, 6, 8, 9, 3, 12, 11]
let numerosOrdenados = numeros.sorted(by: <)
print(numerosOrdenados)

Definir una clase libro que tenga dos propiedades: titulo y paginas. A continuación crear un array de libros con diferentes títulos y páginas, y ordenar los libros por el título de manera ascendente utilizando el método sorted. Finalmente se deberá mostrar el resultado por pantalla:

class Libro {
    var titulo = ""
    var paginas = 0
    init(_ titulo:String, _ paginas:Int) {
        self.titulo = titulo
        self.paginas = paginas
    }
}

var libros = [Libro("Juego de tronos", 250), Libro("El principito", 100), Libro("Blancanieves", 130)]
let librosOrdenados = libros.sorted(by: {$0.titulo < $1.titulo})
print("Libros ordenados por titulo:")
for libro in librosOrdenados {
    print(libro.titulo)
}

Utiliza el método filter para crear un array llamado multiplos que contenga todos los múltiplos de 3 de un array de enteros que se llame numeros e imprímelo para comprobar el resultado:

...

Utilizando el método reduce, encuentra el número más grande de entre los enteros de un array que se llame numeros e imprímelo:

...

Utilizando el método reduce, une todas las cadenas de un array en una sola añadiendo espacios entre cada una de ellas, e imprime el resultado:

...

Utilizando el método filter sobre un array que contiene los nombres de varias personas, muestra sólo aquellos cuyo nombre tiene más de 5 letras:

... 

Utilizando el método reduce, calcula la suma de todos los enteros de un array, y a continuación calcula la media e imprime el resultado:

...

Utilizando el método map convierte a minúsculas todas las cadenas almacenadas en un array, e imprime el resultado:

...

Utilizando el método map obtén un array con el número de letras que tienen cada una de las cadenas de otro array, e imprime el resultado:

...

Utilizando el método sorted, ordena descendentemente todos los enteros de un array:

...

Utilizando el método sorted, ordena ascendentemente todos los nombres de personas que se encuentran almacenados en un array:

...

Utilizando el código de ejercicios anteriores, crear un array de libros con diferentes autores, títulos y páginas, y ordenar los libros por el número de páginas de manera ascendente y descendente utilizando el método sorted, mostrando finalmente el resultado:

...

Utilizando el código de ejercicios anteriores, crear un array de álbumes de fotos, y ordenarlos de manera ascendente por número de páginas:

...

Utilizando el código de ejercicios anteriores, crear un array de vehículos y ordenarlos de manera ascendente según su velocidad:

...

Swift – Ejercicios resueltos (V)

Crea una clase llamada «Obstaculos» para crear los obstáculos de un videojuego. Debe tener un inicializador con los parámetros de anchura y altura de los obstáculos, que serán las propiedades de la clase. Deberá tener además un método «mostrar» que deberá listar esos datos por pantalla.

Crea un array de 10 obstáculos cuyas alturas y anchuras serán asignadas de forma aleatoria. La altura debe estar entre 40 y 100 píxeles y la anchura entre 90 y 120 píxeles y muestra todos los datos al final.

...

Crea una clase «Punto3D» para representar un punto en un espacio de 3 dimensiones que guarde las coordenadas x, y, z de dicho punto. Debe implementar los siguientes métodos:

  • Un inicializador para establecer los valores x, y, z.
  • Un método para mover dicho punto a otras coordenadas.
  • Un método para calcular la distancia entre el punto que represente el objeto, y el de otro objeto que reciba como parámetro. Para ello se deberá calcular la raiz cuadrada (se puede utilizar el método «squareRoot()» del tipo «Double») de la siguiente expresión: (xb – xa)2 + (yb – ya)2 + (zb – za)2
  • Un método «toString» que devolverá un «String» de la siguiente forma: (x, y, z)
  • Los get y los set para actualizar cada una de las coordenadas de forma individual.

Se deberá desarrollar además una clase de prueba que cree un array de 5 puntos, pidiendo los valores de las coordenadas y calcule y enseñe por pantalla la distancia desde el primer punto al resto.

...

Crear un array de libros utilizando el código de ejercicios anteriores. Se deberá crear un menú de consola con las opciones de añadir nuevo y libro y ver los datos de los libros existentes.

...

Crear un array de documentos utilizando el código de ejercicios anteriores. Se deberá crear un menú con las opciones de añadir nuevo documento o libro, pidiendo desde consola los datos correspondientes según se trate de un tipo u otro. También deberemos desarrollar la opción para ver los datos de los libros existentes.

...

Crear una clase «Puerta» para desarrollar un videojuego con un alto y un ancho y un método para mostrar dichos valores. Crear además una clase «Casa» para el mismo videojuego. Dicha clase contendrá 3 puertas, y tendrá otro método para mostrar por pantalla la palabra «Casa» y los datos de las tres puertas.

...

Crear una clase llamada «FotoAlbum» con un atributo que indique el número de páginas. Deberá tener un inicializador que reciba el número de páginas, y otro al que no se le pase ningún parámetro. Este último deberá crear el foto álbum con 16 páginas por defecto.

Se deberá desarrollar un método para mostrar por pantalla la siguiente expresión: «Soy un foto álbum de N páginas»

Además, se deberá desarrollar otra clase que herede de FotoAlbum y que se llame GranAlbum. Esta clase tendrá un inicializador sin parámetros que se utilice el de la clase base, generando un álbum de 64 páginas por defecto.

Por último, se deberá desarrollar un método para mostrar la siguiente expresión: «Soy un foto álbum de N páginas y soy grande», utilizando la función mostrar de la clase base para mostrar la primera parte del mensaje.

...

Crea una clase que se llame «Encriptador» con dos métodos estáticos para encriptar y desencriptar. Recibirán un «String» por parámetro devolviendo dicha cadena encriptada o desencriptada según el caso. La encriptación se llevará a cabo cambiando las vocales por los siguientes caracteres:

  • a -> |
  • e -> /
  • i -> @
  • o -> $
  • u -> &

Desarrollar una clase para probar dicho encriptador con varios ejemplos, teniendo en cuenta que se deben llamar a los métodos para encriptar o desencriptar sin crear un objeto, simplemente accediendo a la función de la clase con el «.» y pasando la cadena como parámetro de la función.

...

Swift – Ejercicios resueltos (IV)

Desarrollar una clase para comprobar si un año es bisiesto:

class Bisiesto {
    var anyo:Int

    init(_ anyo: Int?) {
        self.anyo = Int(anyo ?? 0)
    }

    func esBisiesto() -> Bool {
        return (anyo % 4 == 0 && anyo % 100 != 0) || anyo % 400 == 0
    }
}

var anyo = Bisiesto(2300)

print(anyo.esBisiesto())

Crea una clase llamada Persona. Esta clase deberá tener un atributo «nombre», de tipo String. También deberá tener un método «setNombre», con un parámetro String, que permita cambiar el valor del nombre. Finalmente, también tendrá un método «saludar», que escribirá en pantalla «Hola, soy » seguido de su nombre. Crea también una clase llamada PruebaPersona. Esta clase deberá contener sólo la función main, que creará dos objetos de tipo Persona, les asignará un nombre a cada uno y les pedirá que saluden.

class Persona {
    var nombre:String = ""
    func setNombre(_ nombre:String) {
        self.nombre = nombre
    }
    func saludar() {
        print("Hola soy \(nombre)")
    }
}

class PruebaPersona {
    func main() {
        let persona1 = Persona()
        let persona2 = Persona()
        
        persona1.setNombre("Pepe")
        persona2.setNombre("Juan")
        
        persona1.saludar()
        persona2.saludar()
    }
}

var prueba = PruebaPersona()
prueba.main()

Para guardar información sobre libros, vamos a comenzar por crear una clase «Libro», que contendrá atributos «autor», «titulo», «ubicacion» (todos ellos Strings) y métodos get y set adecuados para leer su valor y cambiarlo (getAutor, getTitulo, …). Crea también una clase llamada «PruebaLibro». Esta clase deberá contener sólo la función «main», que cree un objeto de la clase «Libro», dé valores a sus tres atributos y luego los muestre.

...

Crea una clase «Coche», con atributos «marca» (texto), «modelo» (texto), «cilindrada» (número entero), potencia (número real) y métodos get y set adecuados para leer su valor y cambiarlo (getMarca, getModelo, …). Crea también una clase llamada «PruebaCoche». Esta clase deberá contener sólo la función «main», que cree un objeto de la clase «Coche», dé valores a sus tres atributos y luego los muestre.

...

Se debe crear una nueva clase «PersonaInglesa». Esta clase deberá heredar las características de la clase «Persona», y añadir un método «tomarTe», que escribirá en pantalla «Estoy tomando té». Crea también una clase llamada PruebaPersona2. Esta clase deberá contener sólo la función main, que creará dos objetos de tipo «Persona» y uno de tipo PersonaInglesa, les asignará un nombre, les pedirá que saluden y pedirá a la persona inglesa que tome té.

...

Crea una clase «Documento», de la que «Libro» heredará todos sus atributos y métodos. Ahora la clase «Libro» contendrá sólo un atributo «paginas», número entero, con sus correspondientes «getPaginas» y «setPaginas». Será la clase «Documento» la que tenga ahora las propiedades «autor», «titulo» y «ubicación».

...

Crea una clase «Vehiculo», de la que heredarán «Coche» y una nueva clase «Moto». La clase «Vehiculo» contendrá todos los atributos y métodos que antes estaban en «Coche», y tanto «Coche» como «Moto» heredarán de ella. Crea otra clase para probar el código.

...

Modificar la clase «PersonaInglesa» para que redefina el método «Saludar», para que escriba en pantalla «Hi, I am » seguido de su nombre; se creará una nueva clase «PersonaItaliana», que deberá heredar las características de la clase «Persona», pero se deberá redefinir el método «Saludar», para que escriba en pantalla «Ciao «; crea también una clase llamada PruebaPersona3, que deberá contener sólo la función «main» y creará un objeto de tipo «Persona», uno de tipo «PersonaInglesa», y uno de tipo «PersonaItaliana», les asignará un nombre, les pedirá que saluden y pedirá a la persona inglesa que tome té.

...

Amplia las clases del tipo persona, para que todas ellas contengan inicializadores. Los inicializadores de casi todas las clases estarán vacíos, excepto el de «PersonaInglesa», que prefijará su nombre a «John». Crea también un inicializador alternativo para esta clase que permita escoger cualquier otro nombre.

				

Ampliar la clase «Libro» para que tenga un inicializador que permita dar valores al autor, al título y la ubicación.

...

Mejora la clase «Coche» para añadir un atributo «cantidadDeRuedas» a la clase «Vehiculo», junto con sus get y set. El inicializador de la clase «Coche» le dará el valor 4 y el inicializador de la clase «Moto» le dará el valor 2.

...

Añade a la clase «Persona» un nuevo método «saludar», que reciba un parámetro, que será el texto que debe decir esa persona cuando salude.

...

Ampliar la clase «Libro» para que tenga un segundo inicializador que permita dar valores al autor y al título, pero no a la ubicación, que tomará el valor por defecto «No detallada».

...

Crear dos nuevos métodos en la clase «Vehiculo»: uno llamado «circular», que fijará su «velocidad» (un nuevo atributo) a 50, y otro «circular(v)», que fijará su velocidad al valor que se indique como parámetro.

...

Escribe una clase llamada «Mensaje» que guarde un «remite», «destino» y «contenido» de tipo String y una fecha de tipo entero (aaaammdd). El remite, destino y contenido deberán tener funciones para consultar y actualizar sus valores, pero las funciones «getFecha» y «setFecha» deberán manipular el valor de la fecha antes de guardarlo y antes de mostrarlo. Se deberá desarrollar un método «mostrar» para imprimir el mensaje de la siguiente forma:

Fecha: dd/mm/aaaa
Remite: xxxxxxxxxx, Destino: xxxxxxxxxx
Mensaje: xxxxxxxxxx

Se deberá crear una clase adicional «PruebaMensaje» donde se pidan los datos del mensaje y se muestren por pantalla. La fecha se deberá pedir en formato «dd/mm/aaaa», y se deberá convertir a un entero con el formato mencionado (se puede utilizar el método «split» del tipo String para separar el día, el mes y el año).

...

Crea una clase llamada «Tablero» que tendrá un atributo llamado «color» y otro llamado «material». Se deberá crear otra clase llamada «Mesa» que tendrá un atributo para guardar el tipo de tablero que tiene. En la mesa además se deberán guardar otros atributos como «altura» y «anchura». El tablero deberá tener un inicializador que asigne los valores por defecto de color «marrón» y material «madera». Se deberán desarrollar los métodos correspondientes para actualizar y consultar las propiedades, y un método mostrar en la clase «Mesa» que muestre todos sus datos, incluyendo los del tablero con el que está hecha. Además, se deberá probar dicho código con una clase adicional.

...

Un centro cultural se dedica al préstamo de dos tipos de materiales de préstamo: discos y libros. Para los dos se debe guardar información general, como su código identificativo, el título y el autor. En el caso de los libros, almacenaremos también su número de páginas, y para los discos, el nombre de la discográfica. Al centro cultural acuden una serie de clientes, de los que se guarda su DNI y nombre, que realizan una serie de peticiones de discos o libros, como mucho hasta 5 peticiones. Para cada petición se guarda la fecha de inicio y fin del préstamo. Crea todas las clases necesarias y los métodos para gestionar toda esta información, junto con una clase adicional para probarlo. Se necesitarán métodos del estilo «agregaPeticion» que añadirá una petición nueva dentro del cliente, comprobando que no llegue al máximo de préstamos.

...

Calculadora con Swift

Modo consola

Primer número: 1
Operación: +
Segundo número: 4
Resultado: 5

Primer número: r
Error

Primer número: 4
Operación: m
Error

Primer número: 1
Operación: /
Segundo número: 0
No se puede dividir por cero

Primer número: 4
Operación: -
Segundo número: 6
Resultado: -2

Primer número: 
...
enum OperacionCalculadora {
    case sumar, restar, multiplicar, dividir
    
    init?(_ boton:String) {
        switch boton {
            case "+": self = .sumar
            case "-": self = .restar
            case "*": self = .multiplicar
            case "/": self = .dividir
            default: return nil
        }
    }
    
    func calcular(_ n1: Int, _ n2: Int) -> Int {
        switch self {
            case .sumar: return n1 + n2
            case .restar: return n1 - n2
            case .multiplicar: return n1 * n2
            case .dividir: return n1 / n2
        }
    }
}

var n1:Int? = 0, n2:Int? = 0
var operacion:OperacionCalculadora? = nil
var pantalla:String = "0"

func actualizaNumero(_ boton:String) -> Int? {
    n1 = Int(pantalla)
    n2 = Int(boton)
    if n2 != nil {
        pantalla = boton
    }
    return n2
}

func actualizaOperacion(_ boton:String) -> OperacionCalculadora? {
    operacion = OperacionCalculadora(boton)
    return operacion
}

func realizaCalculo() -> Bool {
    if n2 == 0 && operacion == .dividir {
        print("No se puede dividir por cero\n")
        return false
    }
    pantalla = String(operacion!.calcular(n1!, n2!))
    return true
}

repeat {
    print("Primer número: ", terminator:"")
    if actualizaNumero(readLine()!) == nil {
        print("Error\n")
        continue 
    }
    print("Operación: ", terminator:"")
    if actualizaOperacion(readLine()!) == nil {
        print("Error\n")
        continue
    }
    print("Segundo número: ", terminator:"")
    if actualizaNumero(readLine()!) == nil {
        print("Error\n")
        continue 
    }
    
    if realizaCalculo() == true {
        print("Resultado: " + pantalla + "\n")
    }
} while true

Aplicación iOS

//
//  ViewController.swift
//  Calculadora
//

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet var pantalla: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    enum OperacionCalculadora {
        case sumar, restar, multiplicar, dividir
        
        init?(_ boton:String) {
            switch boton {
                case "+": self = .sumar
                case "-": self = .restar
                case "*": self = .multiplicar
                case "/": self = .dividir
                default: return nil
            }
        }
        
        func calcular(_ n1: Int, _ n2: Int) -> Int {
            switch self {
                case .sumar: return n1 + n2
                case .restar: return n1 - n2
                case .multiplicar: return n1 * n2
                case .dividir: return n1 / n2
            }
        }
    }
    
    var n1:Int? = 0, n2:Int? = 0, borraNumero = false
    var operacion:OperacionCalculadora? = nil
    
    // Ejecutar al pulsar los botones del 0 al 9
    @IBAction func actualizaNumero(_ boton:UIButton) {
        if pantalla.text == "0" || borraNumero == true {
            pantalla.text = ""
            borraNumero = false
        }
        pantalla.text = pantalla.text! + boton.currentTitle!
    }
    
    // Ejecutar al pulsar los botones de +, -, *, /
    @IBAction func actualizaOperacion(_ boton:UIButton) {
        operacion = OperacionCalculadora(boton.currentTitle!)
        n1 = Int(pantalla.text!)!
        borraNumero = true
    }
    
    // Ejecutar al pulsar el botón de =
    @IBAction func realizaCalculo() {
        n2 = Int(pantalla.text!)!
        if n2 == 0 && operacion == .dividir {
            muestraError("No se puede dividir por cero")
        }
        else {
            pantalla.text = String(operacion!.calcular(n1!, n2!))
        }
        borraNumero = true
    }

    func muestraError(_ mensaje:String) {
        let alert = UIAlertController(title:"Error", message:mensaje, preferredStyle:.alert)
        
        let action = UIAlertAction(title:"OK", style:.default, handler:nil)
        
        alert.addAction(action)
        
        show(alert, sender:nil)
    }
}

Swift – Ejercicios resueltos (II)

Funciones y operadores aritméticos

Sumar dos números y devolver el resultado:

func suma(_ num1:Int, _ num2:Int) -> Int {
    return num1 + num2
}
let num1 = 5
let num2 = 8
print("\(num1) + \(num2) = \(suma(num1, num2))")

Calcular el número de segundos que suman en total un número determinado de años:

func segundosAnyo(_ anyos:Int) -> Int {
    let dias = 365
    let horas = 24
    let segundos = 3600
    return dias * horas * segundos * anyos
}
let anyos = 3
print("La cantidad de segundos en \(anyos) años es \(segundosAnyo(anyos))")

Calcular la cantidad total de píxeles que tiene una pantalla dada su altura y anchura en píxeles:

func pixeles(alto:Int, ancho:Int) -> Int {
    return(alto * ancho)
}
let alto = 720
let ancho = 480
print("La cantidad de píxeles de una pantalla de \(alto)x\(ancho) es \(pixeles(alto:720, ancho:480))")

Intercambiar el valor de dos variables:

func intercambiar(_ a:inout Int, _ b:inout Int) {
    let aux = a
    a = b
    b = aux
}
var num1 = 5
var num2 = 10
intercambiar(&num1, &num2)
print("El primer número es: \(num1) y el segundo es: \(num2)")

Dado un número, imprimir el último dígito:

func ultimo(_ num:Int) -> Int {
    return num % 10
}
let num = 2479
print("La última cifra de \(num) es \(ultimo(num))")

Dada la edad de un perro, calcular la edad equivalente en humanos, teniendo en cuenta que un año para una persona equivale a 7 años para un perro:

func edadHumano(_ edadPerro:Int) -> Int {
    return edadPerro * 7
}
let edadPerro = 7
print("\(edadPerro) años de un perro equivalen a \(edadHumano(edadPerro)) años de un humano")

Funciones y control de flujo

Dado un número, comprobar si es par o no:

func esPar(_ num:Int) -> Bool {
    return num % 2 == 0
}

let num = 24

// Con if
if esPar(num) {
    print("El numero \(num) es par")
}
else {
    print("El numero \(num) es impar")
}

// Con el operador ?
print("El numero \(num) es " + (esPar(num) ? "par" : "impar"))

Dados dos números, comprobar si el primero es divisible entre el segundo:

func esDivisible(_ num1:Int, _ num2:Int) -> Bool {
    return num2 != 0 && num1 % num2 == 0
}

let num1 = 3
let num2 = 1

// Con if
if esDivisible(num1, num2) {
    print("El número \(num1) es divisible entre \(num2)")
}
else {
    print("El número \(num1) no es divisible entre \(num2)")
}

// Con el operador ?
print("El número \(num1) \(esDivisible(num1, num2) ? "" : "no") es divisible entre \(num2)")

Funciones y tuplas

Dada una cantidad determinada de chicos y chicas, calcular el porcentaje de cada uno respecto al total:

func calcularPorcentajes(hombres:Int, mujeres:Int) -> (hombres:Int, mujeres:Int) {
    let total = hombres + mujeres
    let porcentajeHombres = (hombres * 100) / total
    let porcentajeMujeres = (mujeres * 100) / total

    return (porcentajeHombres, porcentajeMujeres)
}

let hombres = 12
let mujeres = 15
let porcentaje = calcularPorcentajes(hombres:12, mujeres:15)

print("De \(hombres + mujeres) personas, \(mujeres) son mujeres y \(hombres) son hombres, es decir, \(porcentaje.hombres)% de hombres y \(porcentaje.mujeres)% de mujeres")

Disponemos de dos tuplas de tipo (Int,Int) que representan dos fracciones. El primer valor en cada tupla representa el numerador y el segundo valor representa el denominador. Utilizando una función, crear una nueva tupla también de tipo (Int,Int) que contenga el resultado de sumar las dos fracciones:

func suma(_ fraccion1:(Int, Int), _ fraccion2:(Int, Int)) -> (Int, Int) {
    let numerador = fraccion1.0 * fraccion2.1 + fraccion2.0 * fraccion1.1
    let denominador = fraccion1.1 * fraccion2.1 

    return (numerador, denominador)
}

let fraccion1 = (1, 2)
let fraccion2 = (2, 3)
print("La suma de \(fraccion1) y \(fraccion2) es \(suma(fraccion1, fraccion2)))

Escribir el código necesario para jugar a piedra, papel, tijeras, cumpliendo las siguientes especificaciones:

  • Se debe definir una enumeración con tres posibles casos:  .piedra.papel.tijeras.
  • Se debe definir una segunda enumeración con tres posibles casos:  .gana.empata.pierde.
  • Escribir una función que reciba la elección de cada jugador y devuelva el resultado correspondiente al primer jugador.
enum Mano {
    case piedra, papel, tijeras
}

enum Resultado {
    case gana, empata, pierde
}

func jugar(jugador1:Mano, jugador2:Mano) -> Resultado {
    if jugador1 == jugador2 { return .empata }

    if jugador1 == .piedra  && jugador2 == .tijeras || 
       jugador1 == .papel   && jugador2 == .piedra  ||
       jugador1 == .tijeras && jugador2 == .papel { return .gana }

    return .pierde
}

print(jugar(jugador1:.papel, jugador2:.tijeras))

Parámetros variádicos

Calcular la suma de un número indeterminado de fracciones:

func suma(_ fracciones:(Int, Int)...) -> (Int, Int) {
    var resultado = (0, 1)

    for fraccion in fracciones {
        resultado.1 *= fraccion.1
    }
    for fraccion in fracciones {
        resultado.0 += (resultado.1 / fraccion.1) * fraccion.0
    }    

    return resultado
}

print(suma((1,2), (3,4), (5,2), (4,3)))

Swift – Ejercicios resueltos (I)

Variables, constantes y operadores aritméticos

Dadas dos variables, calcular la suma, almacenar el resultado en otra variable e imprimir el resultado:

let num1 = 5
let num2 = 8
let suma = num1 + num2
print("\(num1) + \(num2) = \(suma)")

Calcular el número de segundos en un año almacenando dicho valor en una variable:

let dias = 365
let horas = 24
let segundos = 3600
let segundosAnyo = dias * horas * segundos
print("La cantidad de segundos en un año es \(segundosAnyo)")

Partiendo de la anchura y la altura de una pantalla en píxeles, calcular el número total de píxeles de dicha pantalla guardando el resultado en otra variable:

let alto = 720
let ancho = 480
let pixeles = alto * ancho
print("La cantidad de pixeles es \(pixeles)")

Dadas dos variables, intercambiar sus valores:

var num1 = 4
var num2 = 8

let aux = num2
num2 = num1
num1 = aux

print("El primer numero es: \(num1) y el segundo es: \(num2)")

Dado un número, imprimir el último dígito:

let num = 2479
print("La última cifra de \(num) es \(num % 10)")

Dada la edad de un perro, imprimir la edad equivalente en humanos, teniendo en cuenta que un año para una persona equivale a 7 años para un perro:

let edadPerro = 7
let edadHumano = edadPerro * 7
print("\(edadPerro) años de un perro equivalen a \(edadHumano) años de un humano")

Dada una cantidad determinada de chicos y chicas, imprimir el porcentaje de cada uno respecto al total:

let hombres = 12
let mujeres = 15
let total = hombres + mujeres

let porcentajeHombres = (hombres * 100) / total
let porcentajeMujeres = (hombres * 100) / total

print("De \(total) alumnos, \(mujeres) son mujeres y \(hombres) son hombres, es decir, \(porcentajeHombres)% de hombres y \(mujeres)% de mujeres")

Control de flujo

Dados dos números, compararlos e imprimir el mayor de ellos:

let num1 = 3
let num2 = 4
if num1 > num2 {
    print("El número \(num1) es mayor que \(num2)")
}
else if num2 > num1 {
    print("El número \(num2) es mayor que \(num1)")
}

Dado un número, imprimir un mensaje indicando si es par o impar:

let num = 23

// Con if
if num % 2 == 0 {
    print("El numero \(num) es par")
}
else {
    print("El numero \(num) es impar")
}

// Con el operador ?
print("El numero \(num) es " + (num % 2 == 0 ? "par" : "impar"))

Dados dos números, imprimir un mensaje diciendo si el primero es divisible entre el segundo o no:

let num1 = 3
let num2 = 1

if num2 != 0 && num1 % num2 == 0  {
    print("El número \(num1) es divisible entre \(num2)")
}
else if num2 != 0 && num1 % num2 != 0 {
    print("El número \(num1) no es divisible entre \(num2)")
}
else {
    print("No se puede dividir entre 0")
}

Dadas tres variables, comparar el valor que contienen e indicar si todas ellas son diferentes, o si por el contrario, dos variables o las tres contienen el mismo valor:

var a = 2
var b = 2
var c = 2

if (a == b) || (a == c) || (b == c) {
    print("Al menos dos variables tienen el mismo valor")
} else {
    print("Todas las variables tienen valores diferentes")
}

Disponemos de dos variables que indican los días que hace que hemos comprado leche y huevos respectivamente. Si hace más de 2 días que compramos la leche deberemos imprimir que ya está caducada, y si hace más de 7 días que compramos los huevos, imprimiremos que están caducados. Si la leche y los huevos no estén caducados, se deberá imprimir un mensaje indicando que ambos están en buen estado:

var diasLeche = 6
var diasHuevos = 12

if diasLeche <= 2 && diasHuevos <= 7 {
    print("La leche y los huevos están en buen estado")
} else {
    if diasLeche > 2 {
        print("La leche está caducada")
    }
    if diasHuevos > 7 {
        print("Los huevos están caducados")
    }
}

Dado un entero que indique un año cualquiera, indicar si dicho año es bisiesto o no, teniendo en cuenta que un año es bisiesto si es divisible entre 4 y no es divisible entre 100, y también si es divisible entre 400 (2000 y 2400 sí son bisiestos. 2100, 2200 y 2300 no lo son):

let anyo = 2018

let divisibleEntre4 = anyo % 4 == 0
let divisibleEntre100 = anyo % 100 == 0
let divisibleEntre400 = anyo % 400 == 0

if divisibleEntre4 && (!divisibleEntre100 || divisibleEntre400) {
    print("El año \(anyo) es bisiesto")    
}
else {
    print("El año \(anyo) no es bisiesto") 
}

Generar un número aleatorio entre 1 y 3 (ambos incluidos) simulando que lanzamos una moneda, de forma que se imprima uno de los tres posibles valores (cara, cruz o canto). Se puede utilizar la función random de la siguiente forma: Int.random(in:1...3)

let moneda = Int.random(in:1...3)

if      moneda == 1 { print("Cara")  } 
else if moneda == 2 { print("Cruz")  } 
else                { print("Canto") }

Dados cuatro valores numéricos, imprimir el más pequeño:

let a = 7, b = 4, c = 2, d = 6

var min = a

if b < min { min = b }

if c < min { min = c }

if d < min { min = d }

print(min)

Imprimir si un número es divisible entre 3 y 5 al mismo tiempo:

let numero = 135

// Con if
if numero % 3 == 0 && numero % 5 == 0 {
    print("\(numero) es divisible entre 3 y 5")
} else {
    print("\(numero) no es divisible entre 3 y 5")
}

// Con el operador ?
print("\(numero) \(numero % 3 == 0 && numero % 5 == 0 ? "" : "no") es divisible entre 3 y 5")

Escribir un switch que imprima las siguientes cadenas utilizando los siguientes intervalos dependiendo de una variable que contiene una distancia:

  1. «Aquí» si la distancia es 0.
  2. «Bastante cerca» si la distancia es mayor que 0 y menor que 5.
  3. «Cerca» si la distancia está entre 5 y 15.
  4. «Más o menos cerca» si la distancia está entre 15 y 40, ambos incluidos.
  5. «Lejos» si la distancia es mayor que 40.
let distancia:UInt = 15

switch distancia {
    case 0:
        print("Aquí")
    case 1..<5:
        print("Bastante cerca")
    case 5..<15:
        print("Cerca")
    case 15...40:
        print("Más o menos cerca")
    default:
        print("Lejos")
}

Tenemos una cadena que indica la descripción de un animal. Si el animal es un «gato» debemos imprimir un mensaje indicándolo. Si es un «gato muy grande», debemos decir que el animal tal vez sea un tigre, y en caso contrario indicaremos que es otro tipo de animal:

let animal = "gato muy grande"

switch animal {
    case "gato":
        print("El animal es un gato")
    case "gato muy grande":
        print("El animal tal vez es un tigre")
    default:
        print("El animal no es ni un gato ni un tigre")
}

Utilizando un switch imprimir la cadena «Eres un superhéroe» si tu nombre es «Clark Kent» o «Bruce Wayne», y «Eres una persona normal» en caso contrario:

let nombre = "Bruce Wayne"

switch nombre {
    case "Clark Kent", "Bruce Wayne":
        print("Eres un superhéroe")
    default:
        print("Eres una persona normal")
}

Arrays

Crear de dos formas diferentes un array que contenga los siguientes enteros 5, 8, 10, 16, 23, 40:

var array1: [Int] = [5, 8, 10, 16, 23, 40]
var array2 = [5, 8, 10, 16, 23, 40]
print(array1)
print(array2)

Crear de dos formas diferentes un array que no pueda ser modificado y que contenga los siguientes enteros: 5, 8, 10, 16, 23, 40

let array1: [Int] = [5, 8, 10, 16, 23, 40]
let array2 = [5, 8, 10, 16, 23, 40]
print(array1)
print(array2)

Añade de dos formas diferentes los valores 118, 137, y 5615 al final del siguiente array: [5, 8, 10, 16, 23, 40]

var array1 = [5, 8, 10, 16, 23, 40]
var array2 = [5, 8, 10, 16, 23, 40]
let array3 = [118, 137, 5615]

array1.append(contentsOf: array3)
array2 += array3

print(array1)
print(array2)

Reemplazar el valor 16 con el valor 45 en el siguiente array: [5, 8, 10, 16, 23, 40]

var array = [5, 8, 10, 16, 23, 40]

array[3] = 45 

print(array)

Reemplaza los valores 8, 10, y 16 con los valores 1, 2, 3, 4, 5 y 6 en el siguiente array: [5, 8, 10, 16, 23, 40]

var array = [5, 8, 10, 16, 23, 40]

array[1...3] = [1, 2, 3, 4, 5, 6]

print(array)

Enumeraciones y tuplas

Definir un array de tuplas que tengan 2 campos cada una, para guardar el nombre y primer apellido de 5 personas:

var personas = [(nombre: "Juan", apellido: "Rubio"),
                (nombre: "Pepe", apellido: "García"),
                (nombre: "Luis Enrique", apellido: "Peinado"),
                (nombre: "Álvaro", apellido: "Sánchez"),
                (nombre: "Pablo", apellido: "Ruiz")]                          

for persona in personas { print(persona) }

Partiendo de dos valores cualesquiera, formar una tupla indicando cuál de esos dos valores es el menor y cuál el mayor:

let a = 5, b = 6
let resultado = a < b ? (menor:a, mayor:b) : (menor:b, mayor:a)
print(resultado)

Definir una enumeración para tener un listado de varios tipos de dispositivos de Apple:

enum DispositivoApple {
    case iPhone
    case iPad
    case iWatch
}

let miDispositivo = DispositivoApple.iPhone
print(miDispositivo)

Disponemos de un array que indica los movimientos del personaje de un videojuego, y también conocemos su posición original. Un paso .arriba incrementará la coordenada y en 1. Un paso .abajo decrementará la coordenada y en 1. Un paso a la  .derecha incrementará la coordenada x en 1. Un paso a la .izquierda decrementará la coordenada x en 1. Se debe imprimir la ubicación final del personaje después de realizar los movimientos indicados:

enum Direccion {
    case arriba, abajo, izquierda, derecha
}

var ubicacion = (x: 0, y: 0)
let pasos:[Direccion] = [.abajo, .abajo, .derecha, .arriba]

for paso in pasos {
    switch paso {
        case .arriba:    ubicacion.y += 1
        case .abajo:     ubicacion.y -= 1
        case .derecha:   ubicacion.x += 1
        case .izquierda: ubicacion.x -= 1
    }
}

print(ubicacion)

Escribir el código necesario para jugar a piedra, papel, tijeras, utilizando una enumeración con los tres posibles casos:  .piedra.papel.tijeras:

enum Mano {
    case piedra, papel, tijeras
}

let jugador1 = Mano.papel
let jugador2 = Mano.tijeras

if jugador1 == jugador2 { 
    print("Empate") 
}
else if jugador1 == .piedra  && jugador2 == .tijeras || 
        jugador1 == .papel   && jugador2 == .piedra  ||
        jugador1 == .tijeras && jugador2 == .papel { 
    print("Gana jugador 1") 
}
else { 
    print("Pierde jugador 1") 
}

Utilizando una enumeración de tipos de monedas y un array de tuplas que especifique el número de monedas que tenemos de cada tipo, calcular e imprimir el cantidad total de dinero:

enum TipoMoneda {
    case cents5, cents10, cents20, cents50, euro1, euro2
}

let monedas:[(cantidad:Int,tipo:TipoMoneda)] = [(2,.cents10), (5,.euro1), (3,.euro2)]

var total = 0

for (cantidad, tipo) in monedas {
    switch tipo {
        case .cents5:
            print("\(cantidad) monedas de 5 céntimos")
            total += cantidad * 5
        case .cents10:
            print("\(cantidad) monedas de 10 céntimos")
            total += cantidad * 10
        case .cents20:
            print("\(cantidad) monedas de 20 céntimos")
            total += cantidad * 20
        case .cents50:
            print("\(cantidad) monedas de 50 céntimos")
            total += cantidad * 50
        case .euro1:
            print("\(cantidad) monedas de 1 euro")
            total += cantidad * 100
        case .euro2:
            print("\(cantidad) monedas de 2 euros")
            total += cantidad * 200
    }
}

print("Total: \(Double(total)/100.0) euros")

Disponemos de un array con los bocadillos que quieren pedir unos amigos en un bar. Antes de llamar al camarero se debe crear otro array que contenga tuplas indicando el tipo de bocadillo y el número de bocadillos que quieren pedir de ese tipo:

enum TipoBocadillo {
    case tortilla, calamares, queso
}

let bocadillos:[TipoBocadillo] = [.tortilla, .tortilla, .calamares, .queso, .calamares, .calamares, .queso]

var listaCamarero:[(tipo:TipoBocadillo, cantidad:Int)] = []

for bocadillo in bocadillos {
    var i = 0
    while i < listaCamarero.count {
        if (listaCamarero[i].tipo == bocadillo) {
            listaCamarero[i].cantidad += 1
            break
        }
        i += 1
    } 
    if i >= listaCamarero.count {
        listaCamarero += [(bocadillo, 1)]        
    }
}

for bocadillo in listaCamarero {
    print("\(bocadillo.cantidad) bocadillos de \(bocadillo.tipo)")
}