Rutas
/
Elixir
Elixir
/
Ejercicios
/
Coche teledirigido
Coche teledirigido

Coche teledirigido

Ejercicio de aprendizaje

Introducción

Estructuras

Las estructuras son una extensión construida sobre los mapas y proporcionan comprobaciones en tiempo de compilación y valores por defecto. Una estructura recibe el nombre del módulo en el que se define. Para definir una estructura, usa el constructor defstruct. El constructor normalmente va justo después de la definición del módulo. defstruct acepta una lista de átomos (para que los valores por defecto sean nil) o una lista de palabras clave (para valores por defecto especificados). Los campos sin valores por defecto deben preceder a los campos con valores por defecto.

defmodule Plane do
  defstruct [:engine, wings: 2]
end

plane = %Plane{}
# => %Plane{engine: nil, wings: 2}

Acceder a los campos y actualizarlos

Como las estructuras se construyen sobre mapas, podemos usar la mayoría de las funciones de mapas para obtener y manipular valores. El comportamiento Access no está implementado para las estructuras. En su lugar, se recomienda usar el operador de acceso estático . para acceder a los campos de la estructura.

  • obtener/consultar los valores de los campos:

    plane = %Plane{}
    plane.engine
    # => nil
    Map.fetch(plane, :wings)
    # => {:ok, 2}
    
  • actualizar los valores de los campos

    plane = %Plane{}
    %{plane | wings: 4}
    # => %Plane{engine: nil, wings: 4}
    

Coincidencia de patrones

Las estructuras se pueden usar en la coincidencia de patrones con o sin el nombre de la estructura.

plane = %Plane{}
%Plane{wings: wings} = plane
%{wings: wings} = plane

Al incluir el nombre de la estructura en el patrón, puedes asegurarte de que tanto el lado izquierdo como el derecho sean estructuras del mismo tipo.

defmodule Helicopter do
  defstruct [:engine, rotors: 1]
end

%Plane{} = %Helicopter{}
# => (MatchError) no match of right hand side value: %Helicopter{engine: nil, rotors: 1}

Forzar la inicialización de los valores de los campos

Podemos usar el atributo de módulo @enforce_keys con una lista de las claves de los campos para asegurarnos de que los valores se inicialicen cuando se crea la estructura. Si una clave no está en la lista, su valor será nil, como se ve en el ejemplo anterior. Si una clave forzada no se inicializa, se lanza un error.

defmodule User do
  @enforce_keys [:username]
  defstruct [:username]
end

%User{}
# => (ArgumentError) the following keys must also be given when building struct User: [:username]

Instrucciones

En este ejercicio vas a jugar con un coche teledirigido, que por fin has podido comprar después de ahorrar lo suficiente.

Los coches empiezan con la batería llena (100 %). Cada vez que conduces el coche con el mando a distancia, recorre 20 metros y consume un 1 % de la batería. El apodo del coche no se conoce hasta que se crea.

El coche teledirigido tiene una moderna pantalla LED que muestra dos datos:

  • La distancia total recorrida, que se muestra como: "<METERS> meters".
  • La carga restante de la batería, que se muestra como: "Battery at <PERCENTAGE>%".

Si la batería está al 0 %, ya no puedes conducir el coche y la pantalla de la batería mostrará "Battery empty".

1. Crea un coche teledirigido nuevo

Implementa la función RemoteControlCar.new/0 para que devuelva un struct de coche teledirigido nuevo:

RemoteControlCar.new()
# => %RemoteControlCar{
#      battery_percentage: 100,
#      distance_driven_in_meters: 0,
#      nickname: "none"
#    }

El struct requiere el apodo; asegúrate de inicializar un valor en la función new, pero no en el struct.

2. Crea un coche teledirigido nuevo con apodo

Implementa la función RemoteControlCar.new/1 para que devuelva un struct de coche teledirigido nuevo con un apodo:

RemoteControlCar.new("Blue")
# => %RemoteControlCar{
#      battery_percentage: 100,
#      distance_driven_in_meters: 0,
#      nickname: "Blue"
#    }

3. Muestra la distancia

Implementa la función RemoteControlCar.display_distance/1 para que devuelva la distancia tal como se muestra en la pantalla LED:

car = RemoteControlCar.new()
RemoteControlCar.display_distance(car)
# => "0 meters"

Asegúrate de que la función solo acepte un struct RemoteControlCar como argumento.

4. Muestra el porcentaje de batería

Implementa la función RemoteControlCar.display_battery/1 para que devuelva el porcentaje de batería tal como se muestra en la pantalla LED:

car = RemoteControlCar.new()
RemoteControlCar.display_battery(car)
# => "Battery at 100%"

Asegúrate de que la función solo acepte un struct RemoteControlCar como argumento. Si la batería está al 0 %, la pantalla de la batería mostrará «Battery empty».

5. Conducir cambia la batería y la distancia recorrida

Implementa la función RemoteControlCar.drive/1 que:

  • aumenta en 20 el número de metros recorridos
  • consume un 1 % de la batería
RemoteControlCar.new("Red")
|> RemoteControlCar.drive()

# => %RemoteControlCar{
#      battery_percentage: 99,
#      distance_driven_in_meters: 20,
#      nickname: "Red"
#    }

Asegúrate de que la función solo acepte un struct RemoteControlCar como argumento.

6. Ten en cuenta cómo conducir con la batería agotada

Actualiza la función RemoteControlCar.drive/1 para que no aumente la distancia recorrida ni reduzca el porcentaje de batería cuando la batería está agotada (al 0 %):

%RemoteControlCar{
  battery_percentage: 0,
  distance_driven_in_meters: 1980,
  nickname: "Red"
}
|> RemoteControlCar.drive()

# => %RemoteControlCar{
#      battery_percentage: 0,
#      distance_driven_in_meters: 1980,
#      nickname: "Red"
#    }
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Elixir Exercism

¿Listo para empezar Coche teledirigido?

Regístrate en Exercism para aprender y dominar Elixir con 58 conceptos168 ejercicios y mentoría humana real, todo gratis.