content: module Set10a where
  
  import Data.Char
  import Data.List
  
  import Mooc.Todo
  
  ------------------------------------------------------------------------------
  -- Ex 1: Given a list, produce a new list where each element of the
  -- original list repeats twice.
  --
  -- Make sure your function works with infinite lists.
  --
  -- Examples:
  --   doublify [7,1,6]          ==>  [7,7,1,1,6,6]
  --   take 10 (doublify [0..])  ==>  [0,0,1,1,2,2,3,3,4,4]
  
  doublify :: [a] -> [a]
  doublify = todo
  
  ------------------------------------------------------------------------------
  -- Ex 2: Implement the function interleave that takes two lists and
  -- produces a new list that takes elements alternatingly from both
  -- lists like this:
  --
  --   interleave [1,2,3] [4,5,6] ==> [1,4,2,5,3,6]
  --
  -- If one list runs out of elements before the other, just keep adding
  -- elements from the other list.
  --
  -- Make sure your function also works with infinite lists.
  --
  -- Examples:
  --   interleave [1,2,3] [4,5,6]            ==> [1,4,2,5,3,6]
  --   interleave [1,2] [4,5,6,7]            ==> [1,4,2,5,6,7]
  --   take 10 (interleave [7,7,7] [1..])    ==> [7,1,7,2,7,3,4,5,6,7]
  --   take 10 (interleave [1..] (repeat 0)) ==> [1,0,2,0,3,0,4,0,5,0]
  
  interleave :: [a] -> [a] -> [a]
  interleave = todo
  
  ------------------------------------------------------------------------------
  -- Ex 3: Deal out cards. Given a list of players (strings), and a list
  -- of cards (strings), deal out the cards to the players in a cycle.
  --
  -- Make sure your function works with infinite inputs as well!
  --
  -- Examples:
  --   deal ["Hercule","Ariadne"] ["Ace","Joker","Heart"]
  --     ==> [("Ace","Hercule"),("Joker","Ariadne"),("Heart","Hercule")]
  --   take 4 (deal ["a","b","c"] (map show [0..]))
  --     ==> [("0","a"),("1","b"),("2","c"),("3","a")]
  --   deal ("you":(repeat "me")) ["1","2","3","4"]
  --     ==> [("1","you"),("2","me"),("3","me"),("4","me")]
  --
  -- Hint: remember the functions cycle and zip?
  
  deal :: [String] -> [String] -> [(String,String)]
  deal = todo
  
  ------------------------------------------------------------------------------
  -- Ex 4: Compute a running average. Go through a list of Doubles and
  -- output a list of averages: the average of the first number, the
  -- average of the first two numbers, the first three numbers, and so
  -- on.
  --
  -- Make sure your function works with infinite inputs as well!
  --
  -- Examples:
  --   averages [] ==> []
  --   averages [3,2,1] ==> [3.0,2.5,2.0]
  --   take 10 (averages [1..]) ==> [1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5]
  
  
  
  averages :: [Double] -> [Double]
  averages = todo
  
  ------------------------------------------------------------------------------
  -- Ex 5: Given two lists, xs and ys, and an element z, generate an
  -- infinite list that consists of
  --
  --  * the elements of xs
  --  * z
  --  * the elements of ys
  --  * z
  --  * the elements of xs
  --  * ... and so on
  --
  -- Examples:
  --   take 20 (alternate "abc" "def" ',') ==> "abc,def,abc,def,abc,"
  --   take 10 (alternate [1,2] [3,4,5] 0) ==> [1,2,0,3,4,5,0,1,2,0]
  
  alternate :: [a] -> [a] -> a -> [a]
  alternate xs ys z = todo
  
  ------------------------------------------------------------------------------
  -- Ex 6: Check if the length of a list is at least n. Make sure your
  -- function works for infinite inputs.
  --
  -- Examples:
  --   lengthAtLeast 2 [1,2,3] ==> True
  --   lengthAtLeast 7 [1,2,3] ==> False
  --   lengthAtLeast 10 [0..]  ==> True
  
  lengthAtLeast :: Int -> [a] -> Bool
  lengthAtLeast = todo
  
  ------------------------------------------------------------------------------
  -- Ex 7: The function chunks should take in a list, and a number n,
  -- and return all sublists of length n of the original list. The
  -- sublists should be in the order that they appear in the original
  -- list. A sublist means a slice, that is, a list of elements
  -- a,b,c,... that occur in the original list next to each other and in
  -- the same order.
  --
  -- Make sure your function works with infinite inputs. The function
  -- lengthAtLeast can help with this.
  --
  -- Examples:
  --   chunks 2 [1,2,3,4] ==> [[1,2],[2,3],[3,4]]
  --   take 4 (chunks 3 [0..]) ==> [[0,1,2],[1,2,3],[2,3,4],[3,4,5]]
  
  chunks :: Int -> [a] -> [[a]]
  chunks = todo
  
  ------------------------------------------------------------------------------
  -- Ex 8: Define a newtype called IgnoreCase, that wraps a value of
  -- type String. Define an `Eq` instance for IgnoreCase so that it
  -- compares strings in a case-insensitive way.
  --
  -- To help the tests, also implement the function
  --   ignorecase :: String -> IgnoreCase
  --
  -- Hint: remember Data.Char.toLower
  --
  -- Examples:
  --   ignorecase "abC" == ignorecase "ABc"  ==>  True
  --   ignorecase "acC" == ignorecase "ABc"  ==>  False
  
  ignorecase = todo
  
  ------------------------------------------------------------------------------
  -- Ex 9: Here's the Room type and some helper functions from the
  -- course material. Define a cyclic Room structure like this:
  --
  --  * maze1 has the description "Maze"
  --    * The direction "Left" goes to maze2
  --    * "Right" goes to maze3
  --  * maze2 has the description "Deeper in the maze"
  --    * "Left" goes to maze3
  --    * "Right" goes to maze1
  --  * maze3 has the description "Elsewhere in the maze"
  --    * "Left" goes to maze1
  --    * "Right" goes to maze2
  --
  -- The variable maze should point to the room maze1.
  --
  -- Examples:
  --   play maze ["Left","Left","Left"]
  --      ==> ["Maze","Deeper in the maze","Elsewhere in the maze","Maze"]
  --   play maze ["Right","Right","Right","Right"]
  --      ==> ["Maze","Elsewhere in the maze","Deeper in the maze","Maze","Elsewhere in the maze"]
  --   play maze ["Left","Left","Right"]
  --      ==> ["Maze","Deeper in the maze","Elsewhere in the maze","Deeper in the maze"]
  
  data Room = Room String [(String,Room)]
  
  -- Do not modify describe, move or play. The tests will use the
  -- original definitions of describe, move and play regardless of your
  -- modifications.
  
  describe :: Room -> String
  describe (Room s _) = s
  
  move :: Room -> String -> Maybe Room
  move (Room _ directions) direction = lookup direction directions
  
  play :: Room -> [String] -> [String]
  play room [] = [describe room]
  play room (d:ds) = case move room d of Nothing -> [describe room]
                                         Just r -> describe room : play r ds
  
  maze :: Room
  maze = todo
  