2. Extended Examples
1. Example 01
You are designing a system that monitors and regulates the turbine inlet temperature, oil temperature, and oil pressure for an aircraft engine. Every cycle a new reading is taken and appended to a list such as the following:
[851, 841, 800, 756, 640, 390, 201] … where the head of the list is the latest reading taken. The componet you are building is tasked in monitoring for anomalous spikes or drops that may indicate mechanical failure.
You may assume all readings are integers.
Q1: Latest Reading
Implement
EngineMonitor.latest/1
such that it returns the last reading taken from a given list.
Here’s how you can implement EngineMonitor.latest/1
in Elixir to return the last reading taken from a given list:
defmodule EngineMonitor do def latest([latest | _rest]), do: latestend
Given a list, this function extracts and returns the head, which is the latest reading.
For example:
readings = [851, 841, 800, 756, 640, 390, 201]EngineMonitor.latest(readings) # returns 851
Q2: Max Reading
EngineMonitor.max_reading/1
returns the maximum reading from a list:
defmodule EngineMonitor do def max_reading(readings) do Enum.max(readings) endend
Enum.max/1
finds the maximum value in thereadings
list.- The function returns the highest integer from the list.
Example Usage:
readings = [851, 841, 800, 756, 640, 390, 201]EngineMonitor.max_reading(readings) # Returns 851
- Using Recursion:
To implement EngineMonitor.max_reading/1
without using Enum
, you can use recursion to find the maximum value in a list. Here’s how you can do it:
defmodule EngineMonitor do def max_reading([head | tail]) do max_reading(tail, head) end
defp max_reading([], max), do: max
defp max_reading([head | tail], max) do new_max = if head > max, do: head, else: max max_reading(tail, new_max) endend
1. max_reading([head | tail])
: Starts the recursion with the first element of the list as the initial maximum value.
2. max_reading([], max)
: Base case, returns the maximum value when the list is empty.
3. max_reading([head | tail], max)
: Recursive case, updates the maximum value if the current element is greater, then proceeds with the rest of the list.
Example Usage:
readings = [851, 841, 800, 756, 640, 390, 201]EngineMonitor.max_reading(readings) # Returns 851
Q3: Rising Reading
EngineMonitor.rising/1
returns the number of times a reading has risen in a given list, you can compare each element with the next one and count how many times the reading increases.
defmodule EngineMonitor do def rising(readings) do readings |> Enum.chunk_every(2, 1, :discard) |> Enum.count(fn [a, b] -> b > a end) endend
Enum.chunk_every(2, 1, :discard)
: Splits the list into overlapping pairs.Enum.count(fn [a, b] -> b > a end)
: Counts how many pairs have a rising trend.
Example Usage:
readings = [851, 841, 800, 756, 640, 390, 201]EngineMonitor.rising(readings) # Returns 0
readings = [200, 300, 250, 400, 450]EngineMonitor.rising(readings) # Returns 3
This implementation counts how many times a reading has increased compared to the previous one.
Q4: Danger Reading
EngineMonitor.danger?/1
returnstrue
if a dangerous spike or drop in readings (a change of50
or more) is detected, you can compare consecutive readings and check if the difference between them is50
or greater.
defmodule EngineMonitor do def danger?(readings) do readings |> Enum.chunk_every(2, 1, :discard) |> Enum.any?(fn [a, b] -> abs(a - b) >= 50 end) endend
Enum.chunk_every(2, 1, :discard)
: Creates overlapping pairs of consecutive readings.Enum.any?(fn [a, b] -> abs(a - b) >= 50 end)
: Checks if any pair has an absolute difference of50
or more.
Example Usage:
readings = [851, 841, 800, 756, 640, 390, 201]EngineMonitor.danger?(readings) # Returns true (640 -> 390 is a drop of 250)
readings = [200, 220, 230, 240, 245]EngineMonitor.danger?(readings) # Returns false (no spike or drop of 50 or more)
This implementation correctly identifies hazardous conditions based on the defined threshold.
- Using Recursion
To implement EngineMonitor.danger?/1
without using Enum
, you can use recursion to check for dangerous spikes or drops. Here’s how you can do it:
defmodule EngineMonitor do def danger?(readings) do check_danger(readings, nil) end
defp check_danger([], _previous), do: false
defp check_danger([current | rest], nil) do check_danger(rest, current) end
defp check_danger([current | rest], previous) do if abs(current - previous) >= 50 do true else check_danger(rest, current) end endend
1. danger?(readings)
: Starts the recursion by calling check_danger/2
with an initial value of nil
for the previous reading.
2. check_danger([], _previous)
: Base case, returns false
when the list is empty (no dangerous changes found).
3. check_danger([current | rest], nil)
: When starting with the first element, there’s no previous reading to compare to. Continue with the rest of the list.
4. check_danger([current | rest], previous)
: Compares the current reading with the previous one. If the absolute difference is 50
or more, return true
. Otherwise, continue checking the rest of the list.
Example Usage:
readings = [851, 841, 800, 756, 640, 390, 201]EngineMonitor.danger?(readings) # Returns true (640 -> 390 is a drop of 250)
readings = [200, 220, 230, 240, 245]EngineMonitor.danger?(readings) # Returns false (no spike or drop of 50 or more)
This implementation uses recursion to traverse the list and identify any dangerous changes based on the specified threshold.
Q5: Fire Reading
EngineMonitor.fire?/1
detects whether the word “FIRE” appears in a string regardless of case, you can useString.downcase/1
to convert the string to lowercase and then check for the presence of the lowercase equivalent of “FIRE”.
defmodule EngineMonitor do def fire?(text) do String.contains?(String.downcase(text), "fire") endend
1. String.downcase(text)
: Converts the entire input string to lowercase.
2. String.contains?(string, "fire")
: Checks if the lowercase string contains the substring "fire"
.
Example Usage:
EngineMonitor.fire?("The alarm system detected a FIRE") # Returns trueEngineMonitor.fire?("No fire detected") # Returns trueEngineMonitor.fire?("Just a test") # Returns false
This implementation ensures that the check for the word “FIRE” is case-insensitive.