content: import Data.Set (Set, fromList, insert, isSubsetOf, member, size)
  import Data.Bool (bool)
  
  firstNRecamans :: Int -> [Int]
  firstNRecamans n = reverse $ recamanUpto (\(_, i, _) -> n == i)
  
  firstDuplicateR :: Int
  firstDuplicateR = head $ recamanUpto (\(rs, _, set) -> size set /= length rs)
  
  recamanSuperset :: Set Int -> [Int]
  recamanSuperset setInts =
    tail $ recamanUpto (\(_, _, setR) -> isSubsetOf setInts setR)
  
  recamanUpto :: (([Int], Int, Set Int) -> Bool) -> [Int]
  recamanUpto p = rs
    where
      (rs, _, _) =
        until
          p
          (\(rs@(r:_), i, seen) ->
              let n = nextR seen i r
              in (n : rs, succ i, insert n seen))
          ([0], 1, fromList [0])
  
  nextR :: Set Int -> Int -> Int -> Int
  nextR seen i r =
    let back = r - i
    in bool back (r + i) (0 > back || member back seen)
  
  -- TEST ---------------------------------------------------------------
  main :: IO ()
  main =
    (putStrLn . unlines)
      [ "First 15 Recamans:"
      , show $ firstNRecamans 15
      , []
      , "First duplicated Recaman:"
      , show firstDuplicateR
      , []
      , "Length of Recaman series required to include [0..1000]:"
      , (show . length . recamanSuperset) $ fromList [0 .. 1000]
      ]
  