The second of this week’s PWC 268 tasks is called Number Game.
Task 2: Number Game
You are given an array of integers, @ints
, with even number of elements.
Write a script to create a new array made up of elements of the given array. Pick the two smallest integers and add it to new array in decreasing order i.e. high to low. Keep doing until the given array is empty.
Example 1
Input: @ints = (2, 5, 3, 4)
Output: (3, 2, 5, 4)
Round 1: we picked (2, 3) and push it to the new array (3, 2)
Round 2: we picked the remaining (4, 5) and push it to the new array (5, 4)
Example 2
Input: @ints = (9, 4, 1, 3, 6, 4, 6, 1)
Output: (1, 1, 4, 3, 6, 4, 9, 6)
Example 3
Input: @ints = (1, 2, 2, 3)
Output: (2, 1, 3, 2)
Especially after how I wound up doing this week’s task 1, I immediately thought about pattern matching in function definitions. One function to handle the end case when the list is exhausted, and another to handle pulling off the first two elements from the list, and a wrapper function to sort the list and then call the recursive function that does the real work:
defp numberGame([], results) do
results
end
defp numberGame([x | y | rest], results) do
results = Enum.concat(results, [y, x])
numberGame(rest, results)
end
def numberGame(ints) do
sortedInts = Enum.sort(ints)
numberGame(sortedInts, [])
end
$ elixir/ch-2.exs
error: misplaced operator |/2
The | operator is typically used between brackets as the
cons operator:
[head | tail]
where head is a sequence of elements separated by commas
and the tail is the remaining of a list.
It is also used to update maps and structs, via the
%{map | key: value} notation, and in typespecs, such as
@type and @spec, to express the union of two types
│
8 │ defp numberGame([x | y | rest], results) do
│ ^
│
└─ elixir/ch-2.exs:8:23: PWC.grabTwo/2
Oops! Ok, I know how to fix this, and it will be easy, because instead of defining just one numberGame/1
function and two numberGame/2
functions, I can define one numberGame/1
function, two
functions and one numberGame
/2
function:numberGame
/3
# list is empty, return results
defp numberGame([], results) do
results
end
# grab the first elem off list, recurse
defp numberGame([x | rest], results) do
numberGame(x, rest, results)
end
# grab second elem off list, swap them, recurse
defp numberGame(x, [y | rest], results) do
results = Enum.concat(results, [y, x])
numberGame(rest, results)
end
# sort the list and then recursively swap element pairs
def numberGame(ints) do
sortedInts = Enum.sort(ints)
numberGame(sortedInts, [])
end
Which brings me to my final implementation:
#!/usr/bin/env elixir
defmodule PWC do
# list is empty, return results
defp numberGame([], results) do
results
end
# grab the first elem off list, recurse
defp numberGame([x | rest], results) do
numberGame(x, rest, results)
end
# grab second elem off list, swap them, recurse
defp numberGame(x, [y | rest], results) do
results = Enum.concat(results, [y, x])
numberGame(rest, results)
end
# sort the list and then recursively swap element pairs
def numberGame(ints) do
sortedInts = Enum.sort(ints)
numberGame(sortedInts, [])
end
def solution(ints) do
IO.puts("Input: @ints = (" <> Enum.join(ints, ", ") <> ")")
result = PWC.numberGame(ints)
IO.puts("Output: (" <> Enum.join(result, ", ") <> ")")
end
end
IO.puts("Example 1:")
PWC.solution([2, 5, 3, 4])
IO.puts("\nExample 2:")
PWC.solution([9, 4, 1, 3, 6, 4, 6, 1])
IO.puts("\nExample 3:")
PWC.solution([1, 2, 2, 3])
$ elixir/ch-2.exs
Example 1:
Input: @ints = (2, 5, 3, 4)
Output: (3, 2, 5, 4)
Example 2:
Input: @ints = (9, 4, 1, 3, 6, 4, 6, 1)
Output: (1, 1, 4, 3, 6, 4, 9, 6)
Example 3:
Input: @ints = (1, 2, 2, 3)
Output: (2, 1, 3, 2)
The code can be found on GitHub at https://github.com/packy/perlweeklychallenge-club/tree/master/challenge-268/packy-anderson/elixir