«Bersoft» company is working on a new version of its most popular text editor — Bord 2010. Bord, like many other text editors, should be able to print out multipage documents. A user keys a sequence of the document page numbers that he wants to print out (separates them with a comma, without spaces).Your task is to write a part of the program, responsible for «standardization» of this sequence. Your program gets the sequence, keyed by the user, as input. The program should output this sequence in format l1-r1,l2-r2,...,lk-rk, where ri + 1 < li + 1 for all i from 1 to k - 1, and li ≤ ri. The new sequence should contain all the page numbers, keyed by the user, and nothing else. If some page number appears in the input sequence several times, its appearances, starting from the second one, should be ignored. If for some element i from the new sequence li = ri, this element should be output as li, and not as «li - li».For example, sequence 1,2,3,1,1,2,6,6,2 should be output as 1-3,6.

The only line contains the sequence, keyed by the user. The sequence contains at least one and at most 100 positive integer numbers. It's guaranteed, that this sequence consists of positive integer numbers, not exceeding 1000, separated with a comma, doesn't contain any other characters, apart from digits and commas, can't end with a comma, and the numbers don't contain leading zeroes. Also it doesn't start with a comma or contain more than one comma in a row.

Output the sequence in the required format.

import qualified Data.Set as Set
import qualified Data.List as List
import Data.Function

main = do
  line <- getLine
  let list = split line ','
  let set = Set.fromList list
  let pages = Set.elems set
  let sortedPages = sortNumeric pages
  let newPages = group sortedPages (read (head sortedPages) :: Int)
  let strPages = List.intercalate "," newPages
  putStrLn strPages

sortNumeric = List.sortBy (compare `on` (read :: String -> Int))

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [String] -> Int -> [String]
group [] posAnterior = [""]
group (x:xs) posAnterior
    | pos == posAnterior = if xs == [] then [x] else (if (nextPos /= succ pos) then (x : rest) else ((x ++ head rest) : tail rest))
    | pos == succ posAnterior = if xs == [] then ["-" ++ x] else (if (nextPos /= succ pos) then (("-" ++ x) : rest) else rest)
    | otherwise = if xs == [] then [x] else (if (nextPos /= succ pos) then (x : rest) else (x ++ head rest) : tail rest)
    where
      pos = (read x :: Int)
      nextPos = (read (head xs) :: Int)
      rest = group xs pos

import qualified Data.Set as Set
import qualified Data.List as List
import Data.Function

main = do
  line <- getLine
  let list = split line ','
  let set = Set.fromList list
  let pages = Set.elems set
  let sortedPages = sortNumeric pages
  let newPages = foldl group [] sortedPages
  let reversedPages = reverse newPages
  let strPages = List.intercalate "," reversedPages
  putStrLn strPages

sortNumeric = List.sortBy (compare `on` (read :: String -> Int))

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [String] -> String -> [String]
group [] pos = [pos]
group (a:as) pos
  | newPos-1 == ant = (ant2 ++ "-" ++ pos) : as
  | otherwise = pos : (a:as)
  where
    newPos = (read pos :: Int)
    ant = (read (last (split a '-')) :: Int)
    ant2 = head (split a '-')

import qualified Data.Set as Set

-- La funcion rep reemplaza todas las comas en el String dado por espacios.
rep :: String -> String
rep "" = ""
rep (',':xs) = " " ++ rep (xs)
rep (x:xs) = [x] ++ rep (xs)

-- La funcion group se encarga de construir el String deseado
group :: [String] -> Int -> [String]
group [] n = "-":(show n):[] --Si la lista esta vacia (Que siempre lo estara al inicio) se agrega la Int n como String y un guion.
group ("-":x:xs) n
    | (read x) == (pred n) = (show n):"-":restofList -- Si x es predecesor de n, se agrega n en la cabeza.
    | otherwise = "-":(show n):",":restofList -- En caso contrario, se reemplaza el guion por una coma, y se agrega n y un guion.
    where restofList = (x:xs)
group (x:xs) n
    | (read x) == (pred n) = (show n):xs -- Si x es predecesor de n, se reemplaza x por n.
    | otherwise = "-":(show n):",":x:xs -- En caso contrario, se agrega una coma, n y un guion.

-- Al terminar la funcion group la nueva lista puede contener un guion a la cabeza. Esta funcion lo elimina si esta presente.
eraseThing :: [String] -> [String]
eraseThing ("-":xs) = xs
eraseThing x = x

main :: IO ()
main = do
    line <- getLine
    let lineList = map (read :: String -> Int) ((words . rep) line) --Se usa rep y words para separar la String en una lista. Luego se usa map y read para convertirlo en una lista de Int
    let newSet = Set.fromList lineList --Se transforma la lista en Set
    let newList = foldl (group) [] newSet --Se utiliza foldl para construir la String con group, dando una lista vacia y el Set
    let groupLine = (concat . reverse) (eraseThing newList) --Se usa reverse y se concatena la lista, obteniendo el String deseado
    putStr (groupLine)

    import qualified Data.Set as Set
    import Data.List
    stringSplit :: String -> Char -> [String]
    stringSplit [] delim = [""]
    stringSplit (c:cs) delim
      | c == delim = "" : rest
      | otherwise = (c : head rest) : tail rest
        where
          rest = stringSplit cs delim
    ggroup :: [String] -> Int -> [String]
    ggroup list i
      |(length list == 0) = [show i]
      |(elem '-' (last list)) == True = if (stringSplit (last list) '-') !! 1 == show(pred i) then init list ++ [(stringSplit (last list) '-' !! 0) ++ "-" ++ show i] else list ++ [show i]
      |otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]
    main :: IO ()
    main = do
      line <- getLine
      let list = stringSplit line ','
      let intList = map (read::String->Int) list
      let set = Set.fromList intList
      let solution = foldl ggroup [] set
      let parte1 = [a ++ ","| a <- (init solution)]
      let parte2 = parte1 ++ [(last solution)]
      let output = foldl1 (++) parte2
      putStrLn output

    import qualified Data.Set as Set
    import Data.List
    stringSplit :: String -> Char -> [String]
    stringSplit [] delim = [""] --Funcion para hacer split, obtenida en https://jmmv.dev/2006/08/split-function-in-haskell.html
    stringSplit (c:cs) delim    -- Ya que codeforce no deja usar Data.List.Split
      | c == delim = "" : rest
      | otherwise = (c : head rest) : tail rest
        where
          rest = stringSplit cs delim
    ggroup :: [String] -> Int -> [String]    --Funcion group necesaria para hacer trabajar el programa, se nombre ggroup debido a que usar group traía problemas en la compilación
    ggroup list i
      |(length list == 0) = [show i]
      |(elem '-' (last list)) == True = if (stringSplit (last list) '-') !! 1 == show(pred i) then init list ++ [(stringSplit (last list) '-' !! 0) ++ "-" ++ show i] else list ++ [show i]
      |otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]
    main :: IO ()
    main = do  --Aca hacemos funcionar el programa, trabajamos con el input y hacemos las transformaciones necesarias para el funcionamiento.
      line <- getLine
      let list = stringSplit line ','
      let intList = map (read::String->Int) list
      let set = Set.fromList intList
      let solution = foldl ggroup [] set
      let parte1 = [a ++ ","| a <- (init solution)]  --Armamos el output, exceptuando el final para evitar terminar con la ,
      let parte2 = parte1 ++ [(last solution)]     --Ultima parte del output
      let output = foldl1 (++) parte2
      putStrLn output

import System.IO
import Data.Set
import System.Environment
import Data.List as Li

cut :: String -> Char -> [String]
cut [] delim = [""]
cut (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = cut cs delim

qsort:: [Integer] -> [Integer]
qsort [] = []
qsort (x:xs) = qsortleft ++ [x] ++ qsortright
  where qsortleft = qsort [alpha | alpha <-xs, alpha <=x]
        qsortright = qsort [gamma | gamma <-xs, gamma > x]

buildList :: String -> [String]
buildList arr =
  if arr == "" then
    let args = [""] in args
  else do
    let newarr = cut arr ','  in newarr

marx :: [[Integer]] -> Integer -> [[Integer]]
marx [] n = [[n]]
marx [x] n =
  if n -1 == last x
    then
      let list = x++[n] in [list]
  else
    [x]++[[n]]
marx (x:xs) n =
  if n -1 == (last x)
    then
      let list = x++[n] in list:xs
  else
    let lists = x:(marx xs n) in lists

bonito::[String]->[Integer]->[String]
bonito s range =
  if head range == last range
    then let r = show (head range) in s++[r]
  else
    let r = show (head range)++"-"++show(last range) in s++[r]

main = do
  array_n <- getLine
  let str = buildList array_n
      set = fromList str
      listp = toList set
      lastlist = Prelude.map read listp :: [Integer]
      ordlist = qsort lastlist
      final = Li.foldl marx [] ordlist
      listcute = Li.intercalate "," (Li.foldl bonito [] final)
  putStrLn listcute

import qualified Data.Set as S
import qualified Data.Text as T

group :: String -> Int -> String
group "" num = "" ++ show num
group str num
    -- Si tenemos el sucesor y ya teniamos secuencia cambiar el numero de la secuencia
    | succ (read (last (split '-' ult)) :: Int) == num && length ult > 1 && elem '-' ult                                        = replaceNum str num
    -- Si tenemos el sucesor, agregar '-' y luego el numero
    | succ (read (last (split '-' ult)) :: Int) == num                                                                          = str ++ "-" ++ show num
    -- Cualquier otro caso extender con ',' y el siguiente numero
    | otherwise                                                                                = str ++ "," ++ show num
    where ult = (last $ split ',' str)

replaceNum :: String -> Int -> String
replaceNum str num = let    pre = pred num
                            toRepl = T.pack(show pre)
                            repl = T.pack (show num)
                            string = T.pack (str)
                    in  T.unpack(T.replace toRepl repl string)

split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s

toInt :: Char -> Int
toInt c = read (c : []) :: Int

main = do
    inp <- getLine
    let a = concatMap (\x -> if x == ',' then " " else [x]) inp -- Remplazar comas por espacios para usar words
    let set = S.fromList (map read $ words a :: [Int])
    putStrLn (S.foldl group "" set)

import qualified Data.List as List
import qualified Data.Set as Set

main :: IO()
main = do
 input <- getLine
 let inputList = split input ','
 let intList = map(read::String->Int) inputList
 let dataSetList = Set.toList (Set.fromList intList)
 let flipList = foldl (flip (:)) [] dataSetList
 let lastList = foldl group [] flipList
 let returnList = showTuples lastList
 putStrLn returnList

showTuples :: [(Int, Int)] -> String
showTuples [] = ""
showTuples ((x,y):xs)
    |null xs = (if x == y then show x else show x ++ "-" ++ show y)
    |otherwise  = (if x == y then show x ++ "," ++ showTuples(xs) else show x ++ "-" ++ show y ++ "," ++ showTuples(xs))

--Fuente: https://jmmv.dev/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((x,y):xs) n
    |x-1 == n   = ((n,y):xs)
    |otherwise  = [(n,n)] ++ ((x,y):xs)

import qualified Data.List as List
import qualified Data.Set as Set

main :: IO()
main = do
 input <- getLine
 let inputList = split input ','
 let intList = map(read::String->Int) inputList
 let dataSetList = Set.toList (Set.fromList intList)
 let flipList = reverse dataSetList
 let lastList = foldl group [] flipList
 let returnList = showTuples lastList
 putStrLn returnList

showTuples :: [(Int, Int)] -> String
showTuples [] = ""
showTuples ((x,y):xs)
    |null xs = (if x == y then show x else show x ++ "-" ++ show y)
    |otherwise  = (if x == y then show x ++ "," ++ showTuples(xs) else show x ++ "-" ++ show y ++ "," ++ showTuples(xs))

--Fuente: https://jmmv.dev/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((x,y):xs) n
    |x-1 == n   = ((n,y):xs)
    |otherwise  = [(n,n)] ++ ((x,y):xs)

import qualified Data.List as List
import qualified Data.Set as Set

main :: IO()
main = do
 input <- getLine
 let inputList = split input ','
 let intList = map(read::String->Int) inputList
 let dataSet = Set.fromList intList
 let dataSetList = Set.toList (Set.fromList intList)
 let flipList = foldl (flip (:)) [] dataSetList
 let lastList = foldl group [] flipList
 let returnList = showTuples lastList
 putStrLn returnList

showTuples :: [(Int, Int)] -> String
showTuples [] = ""
showTuples ((x,y):xs)
    |null xs = (if x == y then show x else show x ++ "-" ++ show y)
    |otherwise  = (if x == y then show x ++ "," ++ showTuples(xs) else show x ++ "-" ++ show y ++ "," ++ showTuples(xs))

--Fuente: https://jmmv.dev/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((x,y):xs) n
    |x-1 == n   = ((n,y):xs)
    |otherwise  = [(n,n)] ++ ((x,y):xs)

import qualified Data.List as List
import qualified Data.Set as Set

main :: IO()
main = do
 input <- getLine
 let inputList = split input ','
 let intList = map(read::String->Int) inputList
 --let dataSet = Set.fromList intList
 let dataSetList = Set.toList (Set.fromList intList)
 let flipList = foldl (flip (:)) [] dataSetList
 let lastList = foldl group [] flipList
 let returnList = showTuples lastList
 putStrLn returnList

showTuples :: [(Int, Int)] -> String
showTuples [] = ""
showTuples ((x,y):xs)
    |null xs = (if x == y then show x else show x ++ "-" ++ show y)
    |otherwise  = (if x == y then show x ++ "," ++ showTuples(xs) else show x ++ "-" ++ show y ++ "," ++ showTuples(xs))

--Fuente: https://jmmv.dev/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((x,y):xs) n
    |x-1 == n   = ((n,y):xs)
    |otherwise  = [(n,n)] ++ ((x,y):xs)

import qualified Data.List as List
import qualified Data.Set as Set

main :: IO()
main = do
 input <- getLine
 let inputList = split input ','
 let intList = map(read::String->Int) inputList
 let dataset = Set.fromList intList
 let dataSetList = Set.toList (Set.fromList intList)
 let flipList = foldl (flip (:)) [] dataSetList
 let lastList = foldl group [] flipList
 let returnList = showTuples lastList
 putStrLn returnList

showTuples :: [(Int, Int)] -> String
showTuples [] = ""
showTuples ((x,y):xs)
    |null xs = (if x == y then show x else show x ++ "-" ++ show y)
    |otherwise  = (if x == y then show x ++ "," ++ showTuples(xs) else show x ++ "-" ++ show y ++ "," ++ showTuples(xs))

--Fuente: https://jmmv.dev/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((x,y):xs) n
    |x-1 == n   = ((n,y):xs)
    |otherwise  = [(n,n)] ++ ((x,y):xs)

import qualified Data.Set as Set
import qualified Data.Map as Map

--Función pedida por la tarea, separa las páginas en tuplas (n,m) si son un rango o (n,n)
--Si n no pertenece a un rango
group :: [(Int, Int)] -> Int -> [(Int, Int)]
group [] p  = [(p, p)]
group pages p = let
    (p1,p2) = last pages

    in if p == p2 + 1 then (init pages) ++ [(p1,p)] else pages  ++ [(p,p)]

-- Usada para crear la lista con los puros numeros
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
        | c == delim = "" : rest
        | otherwise = (c : head rest) : tail rest
    where
      rest = split cs delim

-- funcion que me escribe el output más una coma al final
writer::[(Int, Int)] -> String
writer [] = ""
writer ((p1,p2):xs) = if p1 == p2 then show p1 ++ "," ++ writer xs else show p1 ++ "-" ++ show p2 ++ "," ++ writer xs

-- funcion para parsear a lista de Int
reader :: [String] -> [Int]
reader = map read
--Función de internet que usé para quitar la coma del final de mi output

remLast::String -> String
remLast "" = ""
remLast cs = init cs

-- main medio confuso, pero lo explicaré
main :: IO ()
main = do
    rawdata <- getLine --input
    let ldata1 =split rawdata ','   -- separo por comas y creo la lista de String
    let ldata2 = reader ldata1 -- Parseo la lista de Int a String
    let sdata = Set.fromList ldata2 -- Lo pedido de pasar a Set
    let ldata3 = Set.toList sdata -- Vuelvo a parsear a Lista por comodidad y
                                  --porque no hay necesidad de seguir trabajando con set
    let finalPages = foldl (group) [] ldata3 -- Hago fold sobre mi lista de tuplas y me apollo de group
    let output = writer finalPages --ocupo mi lista obtenida del foldl group y la pongo como output
    let output2 = remLast output -- arreglo el output quitando la ultima coma
    putStrLn output2

import qualified Data.Set as Set
import qualified Data.Map as Map

group :: [(Int, Int)] -> Int -> [(Int, Int)]
group [] p  = [(p, p)]
group pages p = let
    (p1,p2) = last pages

    in if p == p2 + 1 then (init pages) ++ [(p1,p)] else pages  ++ [(p,p)]

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
        | c == delim = "" : rest
        | otherwise = (c : head rest) : tail rest
    where
      rest = split cs delim

writer::[(Int, Int)] -> String
writer [] = ""
writer ((p1,p2):xs) = if p1 == p2 then show p1 ++ "," ++ writer xs else show p1 ++ "-" ++ show p2 ++ "," ++ writer xs

reader :: [String] -> [Int]
reader = map read

remLast::String -> String
remLast "" = ""
remLast cs = init cs

main :: IO ()
main = do
    rawdata <- getLine
    let ldata1 =split rawdata ','
    let ldata2 = reader ldata1
    let sdata = Set.fromList ldata2
    let ldata3 = Set.toList sdata
    let finalPages = foldl (group) [] ldata3
    let output = writer finalPages
    let output2 = remLast output
    putStrLn output2

import Control.Monad
import Control.Applicative
import Control.Arrow

import Data.List
import Data.Function
import qualified Data.Set as Set

format [] = ""
format (i:[]) = "," ++ show i
format (i:j:is)
    | i+1 == j =
                let (k, is') = continue (j:is)
                in  "," ++ show i ++ "-" ++ show k ++ format is'
    | otherwise = "," ++ show i ++ format (j:is)

continue (j:k:is)
    | j+1 == k  = continue (k:is)
    | otherwise = (j, k:is)
continue (k:[]) = (k, [])
continue [] = error "impossible"

main = do
  pages <- read . (\a -> "[" ++ a ++ "]") <$> getLine :: IO [Int]
  let set = Set.toList $ foldl (flip Set.insert) Set.empty pages
  putStrLn . tail . format $ set

import System.IO
import Data.Char
import Data.List

groups :: [Char] -> Int -> [Char]
groups "" i = show i
groups palabra i = do
    if (lastSymbol 0 palabra=="-")
            then (sinLastNumber palabra)++[x|x<-show i, (lastNumber palabra+1)==i]++[x|x<-(show (lastNumber palabra)++[',']++show i), (lastNumber palabra +1)/=i]
            else palabra++[x|x<-['-']++show i, (lastNumber palabra+1)==i]++[ x|x<-[',']++show i, (lastNumber palabra +1)/=i]

addComa::[Char]-> Int->[Char]
addComa palabra _ = [last palabra]++","

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int

sinLastNumber::[Char]->[Char]
sinLastNumber s= reverse(dropWhile (isDigit) (reverse s))

lastSymbol:: Int->[Char]->[Char]
lastSymbol 0 s= lastSymbol 1 (reverse s)
lastSymbol 1 "" = ""
lastSymbol 1 (x:xs)= do
    if(isDigit x)
        then lastSymbol 1 xs
        else [x]
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main= do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= foldl groups "" sortedSet
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List hiding(group)
import qualified Data.Set as S

group :: [Char] -> Int -> [Char]
group "" i = show i
group palabra i = do
    if (lastSymbol 0 palabra=="-")
            then (sinLastNumber palabra)++[x|x<-show i, (lastNumber palabra+1)==i]++[x|x<-(show (lastNumber palabra)++[',']++show i), (lastNumber palabra +1)/=i]
            else palabra++[x|x<-['-']++show i, (lastNumber palabra+1)==i]++[ x|x<-[',']++show i, (lastNumber palabra +1)/=i]

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int

sinLastNumber::[Char]->[Char]
sinLastNumber s= reverse(dropWhile (isDigit) (reverse s))

lastSymbol:: Int->[Char]->[Char]
lastSymbol 0 s= lastSymbol 1 (reverse s)
lastSymbol 1 "" = ""
lastSymbol 1 (x:xs)= do
    if(isDigit x)
        then lastSymbol 1 xs
        else [x]
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main= do
    line<-getLine
    let sortedSet = S.fromList (map read $ words $deleteComas line :: [Int])
    let finalString= foldl group "" (S.toList sortedSet)
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]

grouping s [] _= s
grouping s (x:xs) flag= do
    if(flag)
        then if(lastNumber s ==(x-1))
            then grouping (reverse (drop (length(show (lastNumber s))) (reverse s)) ++ show x) xs True
            else grouping (s++",") (x:xs) False
        else if(xs==[])
            then grouping (s++ show x) xs False
            else if(x==(head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List hiding(group)
import qualified Data.Set as S

group :: [Char] -> Int -> [Char]
group "" i = show i
group palabra i = do
    if (lastSymbol 0 palabra=="-")
            then (sinLastNumber palabra)++[x|x<-show i, (lastNumber palabra+1)==i]++[x|x<-(show (lastNumber palabra)++[',']++show i), (lastNumber palabra +1)/=i]
            else palabra++[x|x<-['-']++show i, (lastNumber palabra+1)==i]++[ x|x<-[',']++show i, (lastNumber palabra +1)/=i]

addComa::[Char]-> Int->[Char]
addComa palabra _ = [last palabra]++","

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int

sinLastNumber::[Char]->[Char]
sinLastNumber s= reverse(dropWhile (isDigit) (reverse s))

lastSymbol:: Int->[Char]->[Char]
lastSymbol 0 s= lastSymbol 1 (reverse s)
lastSymbol 1 "" = ""
lastSymbol 1 (x:xs)= do
    if(isDigit x)
        then lastSymbol 1 xs
        else [x]
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main= do
    line<-getLine
    let sortedSet = S.fromList (map read $ words $deleteComas line :: [Int])
    let finalString= foldl group "" (S.toList sortedSet)
    putStrLn $ id finalString

import Data.List (sort)

main :: IO ()
main = getLine >>= putStrLn . drop 4 . solve (-1) (-1) . sort . read . ('[':) . (++"]")

solve :: Int -> Int -> [Int] -> String
solve k l [] | k < l = ',' : show k ++ '-' : show l
             | otherwise = ',' : show k
solve k l (x:xs) | l + 1 < x = solve k l [] ++ solve x x xs
                 | otherwise = solve k x xs

import Data.Set

 --funcion split  copiada de https://jmmv.dev/2006/08/split-function-in-haskell.html
stringSplit :: String -> Char -> [String]
stringSplit [] delim = [""]
stringSplit (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = stringSplit cs delim

--funcion que convierte el input ya separado por comas a un set de enteros
toIntSet :: [String] -> Set Int
toIntSet nums = Prelude.foldl (\s n-> insert (read n :: Int) s) empty nums

-- funcion group pedida en las instrucciones. Debido a que esta función será ocupada
-- con un foldl de un Set, se asume que los numeros van a venir en orden ascendiente
-- debido a esto solo se necesita mirar al ultimo elemento de la lista de tuplas
group :: [(Int, Int)] -> Int -> [(Int, Int)]
group [] n = [(n, n)] --caso inicial
group ranges n = let
    -- se toma el último elemento de la lista de tuplas
    (x1,x2) = last ranges

    -- si n pertenece al último rango en la lista, se añade a éste, de lo contrario
    -- se crea un nuevo rango
    in if n == x2 + 1 then (init ranges)++[(x1,n)] else ranges++[(n,n)]

-- Función que transforma los rangos a strings en el formato pedido
rangeToString :: (Int, Int) -> String
rangeToString (x1, x2)
    | x1 == x2 = show x1 -- todos los rangos de la forma n,n pasan a "n"
    |otherwise = (show x1)++"-"++(show x2) -- todos los rangos de la forma a,b pasan a "a-b"

-- Función que recibe el string de input y retorna un string formateado
formatString :: String -> String
formatString unformated = let
    uniqueNums = toIntSet $ stringSplit unformated ',' -- set con todos los numeros
    ranges = Data.Set.foldl (group) [] uniqueNums --pasa el set a una lista de rangos
    formated = Prelude.foldl (\s tup -> s++(rangeToString tup)++",") "" ranges
    in init formated -- se bota el último elemento ya que es una coma

main :: IO ()
main = do
    unformated <- getLine
    putStrLn (formatString unformated)

import Data.Set

 --funcion split  copiada de https://jmmv.dev/2006/08/split-function-in-haskell.html--
stringSplit :: String -> Char -> [String]
stringSplit [] delim = [""]
stringSplit (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = stringSplit cs delim

toIntSet :: [String] -> Set Int
toIntSet nums = Prelude.foldl (\s n-> insert (read n :: Int) s) empty nums

group :: [(Int, Int)] -> Int -> [(Int, Int)]
group [] n = [(n, n)]
group ranges n = let
    (x1,x2) = last ranges
    in if n == x2 + 1 then (init ranges)++[(x1,n)] else ranges++[(n,n)]

rangeToString :: (Int, Int) -> String
rangeToString (x1, x2)
    | x1 == x2 = show x1
    |otherwise = (show x1)++"-"++(show x2)

formatString :: String -> String
formatString unformated = let
    uniqueNums = toIntSet $ stringSplit unformated ','
    ranges = Data.Set.foldl (group) [] uniqueNums
    formated = Prelude.foldl (\s tup -> s++(rangeToString tup)++",") "" ranges
    in init formated

main :: IO ()
main = do
    unformated <- getLine
    putStrLn (formatString unformated)

import qualified Data.Set as Set

qsort :: (Ord t) => [t] -> [t]
qsort [] = []
qsort (x:xs) = let
				left = filter (<=x) xs
				right = filter (>x) xs
				in qsort left ++ [x] ++ qsort right
-----------------------------------------------------------------------------
--function that transform e.g ",1,2,3" in "1-3"
fx :: String -> String
fx acc = if first_one == last_one then first_one else first_one++"-"++last_one
			where
				first_one = head (tail (split' ',' acc))
				last_one = last (split' ',' acc)
-----------------------------------------------------------------------------
-- function who says if num is succ of acc'
fn :: String -> Int -> Bool
fn acc' num = let			--acc' is a string with the last number read
				last' = read acc' :: Int
				in if last' + 1 == num then True else False

-----------------------------------------------------------------------------
-- Function asked in LP
group :: [String] -> Int -> [String]
group [] num = [","++show num]
group acc num = if fn acc' num then init acc ++ [last_element ++ ","++show num] else acc ++ [","++show num]
				where
					last_element = last acc
					acc' = last (split' ',' last_element)

-----------------------------------------------------------------------------
-- Reduce all the string to the format asked in the problem, e.g ",1,2,3" -> "1-3" (in other words, map)
get' :: [String] -> [String]
get' xs = [fx i | i <- xs]

-----------------------------------------------------------------------------
-- Map input to a integer list
getNumbers :: [String] -> [Int]
getNumbers input = [read i :: Int | i <- input]

-----------------------------------------------------------------------------
-- group all numbers from input (in a set as integers)
toGroup :: (Foldable t) => t Int -> [String]
toGroup set = foldl group [] set

-----------------------------------------------------------------------------
--Concatenate all the strings in xs
concatenate :: [String] -> String
concatenate xs = foldl1 (\acc x -> acc++","++x) xs

-----------------------------------------------------------------------------
--I couldn't use splitOn from Data.List.Split so i create my own split'
split' :: Eq a => a -> [a] -> [[a]]
split' x y = func x y [[]]
    where
        func x [] z = reverse $ map (reverse) z
        func x (y:ys) (z:zs) = if y==x then
            func x ys ([]:(z:zs))
        else
            func x ys ((y:z):zs)

-----------------------------------------------------------------------------
main = do
		input <- getLine
		let input' = Set.fromList(getNumbers (split' ',' input))
		let result = get' (toGroup input')
		putStrLn (concatenate result)

-- Desktop\USM\LPs\Haskell
import qualified Data.Set as Set
import Data.List
import System.IO

split :: String -> [String] -- Nos apoyamos de https://jmmv.dev/2006/08/split-function-in-haskell.html
split [] = [""]
split (co:cs)
    | (co == ',')  = "" : resto
    | otherwise = (co : head resto) : tail resto
    where resto = Main.split cs

rango :: String -> Bool
rango "" = False
rango (xo:xs)
    | (xo == '-') = True
    | otherwise = rango xs

group :: [String] -> Int -> [String] --Funcion pedida del tipo a -> b -> a
group paginas xo
    | paginas == [] = [show xo] -- show: http://zvon.org/other/haskell/Outputprelude/show_f.html
    | ((rango (head paginas) == False) && ((read (head paginas)) :: Int) + 1 == xo) = [head paginas ++ "-" ++ show xo] ++ tail paginas
    | ((rango (head paginas) == False) && ((read (head paginas)) :: Int) + 1 /= xo) = [show xo] ++ paginas
    | ((rango (head paginas) == True) && (num == xo)) = [takeWhile (/='-') (head paginas) ++ "-" ++ show xo] ++ tail paginas
    | ((rango (head paginas) == True) && (num /= xo)) = [show xo] ++ paginas
    where
        num = (read (tail (dropWhile (/='-') (head paginas))) :: Int) + 1

lista_a_Int :: [String] -> [Int]
lista_a_Int [] = []
lista_a_Int (xo:xs) = (read xo :: Int) : lista_a_Int xs

qsort :: [Int] -> [Int]
qsort [] = []
qsort (yo:ys) = qsort ysLeft ++ [yo] ++ qsort ysRight
    where
        ysLeft = [a|a <- ys, a <= yo]
        ysRight = [a|a <- ys, a > yo]

main :: IO ()
main = do
    input <- getLine --recibo el input como una lista
    let lista = Main.split input --se hace el split
    let lista_int = lista_a_Int lista --se convierte a una lista de enteros
    let lista_ordenada = qsort lista_int --ordenamos la lista ocupando función aprendida en clases
    let set = Set.fromList lista_ordenada --se convierte a set, de esta forma no hay repetidos
    let set_2 = Set.foldl Main.group [] set --iterar con un foldl sobre set
    let set_3 = Data.List.reverse set_2
    let string = Data.List.intercalate "," set_3
    putStrLn string

import Data.List (sort)
import Data.Set as Set

--esta funcion entrega el ultimo numero consecutivo
--por ejemplo si le pasamos [1,2,3,6] entrega 3 ya que 1->2->3-/>6 en 3 terminan los numeros concecutivos
secuencia :: [Int]->Int
secuencia x = case x of
    [a]    ->  a
    (a:as) ->  if((a+1)==(head as)) then (secuencia as) else a

--esta funcion agrupa las secuencias en una lista de truplas de dos elementos
--[(Inicio Secuencia),(Final Secuencia)] si un numero es menor al final de la secuencia
--si un numero es menor al final de la secuencia significa que esta dentro de esta
group :: [Int] -> Int -> [(Int,Int)]
group x ultimoSec = case x of
    [] -> []
    (a:as) -> if a<=(ultimoSec) then (group as ultimoSec)
            else [(a,secuencia x)] ++ (group as (secuencia x))
            --[(secuencia 1),(secuencia 2), ..., (secuencia n) ]

--se genera el string de las secuencias
stringGroup :: [(Int, Int)] -> String
stringGroup xs = (Prelude.foldl (\s (a,b) ->(
    --si se termino la secuencia actual, se va a la siguiente
    if ((a,b)/=(head xs)) then s ++ ","
    else s) ++ (
        --si el inicio de la secuencia y el final son iguales, entonces la secuencia es de un solo numero
        --si son distintas entonces es una secuencia de mas de un numero, por lo que:
        -- se imprime Inicio-final
        if (a/=b) then ((show a) ++ "-" ++ (show b))
        else (show a)))
        "" xs)

--funcion split de https://jmmv.dev/2006/08/split-function-in-haskell.html
split_at :: String -> Char -> [String]
split_at [] delim = [""]
split_at (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split_at cs delim

main :: IO ()
main = do
    input <- getLine
    let spl = split_at input ','
    let lista = (Prelude.map (read::String->Int) spl)
    let conjNums = Set.fromList lista
    let list1 = toList conjNums
    let grupo = group  list1 0
    let final = stringGroup grupo
    putStrLn (final)

import Data.List (sort)
import Data.Set as Set

split_at :: String -> Char -> [String]
split_at [] delim = [""]
split_at (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split_at cs delim

strGroup:: [(Bool, Bool)] -> [Int] -> String
strGroup [(x,y)] [a] = show a
strGroup (c:cs) (x:xs) = case c of
    (True,True) -> (strGroup cs xs)
    (True,False) -> (show x) ++ "," ++ (strGroup cs xs)
    (False,True) -> show(x) ++ "-" ++ (strGroup cs xs)
    (False,False) -> (show x) ++ "," ++ (strGroup cs xs)

main :: IO ()
main = do
    input <- getLine
    let lista = (Prelude.map (read::String->Int) (split_at input ','))
    let conjutoNums = Set.fromList lista
    let list1 = toList conjutoNums
    let grupo = scanl (\x y -> (elem (pred y) lista,elem (succ y) lista) ) (False, False) list1
    let final = strGroup (tail grupo) list1
    putStrLn (final)

import Data.List (sort)
import Data.Set as Set

--prueba

secuencia :: [Int]->Int
secuencia x = case x of
    [a]    ->  a
    (a:as) ->  if((a+1)==(head as)) then (secuencia as) else a

group :: [Int] -> Int -> [(Int,Int)]
group x ultimoSec = case x of
    [] -> []
    (a:as) -> if a<=(ultimoSec) then (group as ultimoSec)
            else [(a,secuencia x)] ++ (group as (secuencia x))

stringGroup :: [(Int, Int)] -> String
stringGroup xs = (Prelude.foldl (\s (a,b) ->(
    if ((a,b)/=(head xs)) then s ++ ","
    else s) ++ (
        if (a/=b) then ((show a) ++ "-" ++ (show b))
        else (show a)))
        "" xs)

split_at :: String -> Char -> [String]
split_at [] delim = [""]
split_at (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split_at cs delim

main :: IO ()
main = do
    input <- getLine
    let spl = split_at input ','
    let lista = (Prelude.map (read::String->Int) spl)
    let conjNums = Set.fromList lista
    let list1 = toList conjNums
    let grupo = group  list1 0
    let final = stringGroup grupo
    putStrLn (final)

import Prelude
import List
import Char

main = interact q

q = func.lines

func::[String]->String
func (a:xs) = (solve a) ++ "\n" ++ (func xs)
func []     = ""

toInt::String->Integer
toInt = read

toString::Integer->String
toString = show

words' "" = []
words' s =  let (l, s') = break (== ',') s
            in  l : case s' of
                      []      -> []
                      (_:s'') -> words' s''

solve = init.foldr conc "".map tostr.foldr hoge [].map head.group.sort.map toInt.words'
        where
          hoge y []         = [(y,y)]
          hoge y ((a,b):xs) = if (y+1) == a
                              then (y,b):xs
                              else (y,y):(a,b):xs
          tostr (l,r) | l==r      = toString l
                      | otherwise = (toString l) ++"-"++(toString r)
          conc [] b = b
          conc a  b = a++","++b

import qualified Data.Set as S

splitfunc :: String -> [String] --C&P de StackOverflow: https://stackoverflow.com/questions/46580924/haskell-splitting-a-string-by-delimiter

splitfunc [] = [""]
splitfunc (c:cs) | c == ','  = "" : rest
             | otherwise = (c : head rest) : tail rest
    where rest = splitfunc cs

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((a,b):xs) n =
        if a-1 == n
            then ((n,b):xs)
            else [(n,n)] ++ ((a,b):xs)

convert :: [(Int,Int)] -> String
convert ((a,b):xs) =
    if null xs -- Si xs es null, no se agrega "," al final.
        then if a == b
                then show a
                else show a ++ "-" ++ show b
        else if a == b
                then show a ++ "," ++ convert(xs)
                else show a ++ "-" ++ show b ++ "," ++ convert(xs)
main :: IO()
main = do
 line <- getLine
 let linelist = splitfunc line
 let intlist = map(read::String->Int) linelist
 let dataset = S.fromList intlist
 let settolist = S.toList dataset
 let finallist = foldl (flip (:)) [] settolist -- Se da vuelta la lista, para trabajar con la cabeza
 let final = foldl group [] finallist
 let a = convert final
 putStrLn a

import qualified Data.Set as Set

splitComma :: String -> [String]
splitComma [] = [""]
splitComma (x:xs)
        | x == ',' = "" : splitComma xs
        | otherwise = (x : head rest) : tail rest
    where rest = splitComma xs

toString :: [(Int,Int)] -> String
toString [] = ""
toString ((a,b):xs)
    | a /= b = if xs /= [] then show a ++ "-" ++ show b ++ "," ++ toString xs else show a ++ "-" ++ show b
    | otherwise = if xs /= [] then show a ++ "," ++ toString xs else show a

toListofTuples :: [Int] -> [(Int,Int)]
toListofTuples [] = []
toListofTuples [a] = [(a,a)]
toListofTuples (a:b:xs)
    | a + 1 == b = (a , result) : toListofTuples new_list
    | otherwise = (a,a) : toListofTuples (b:xs)
    where result = maxN (b:xs) a
          new_list = filter (>result) (b:xs)

maxN :: [Int] -> Int -> Int
maxN (x:xs) a
    | xs == []  && a+1 == x = a+1
    | xs == []  && a+1 /= x = a
    | a + 1 == x = maxN xs (a+1)
    | otherwise = a

main = do
    input <- getLine -- "1,2,3,1,1,2,6,6,2"
    let splitted_input = splitComma input
    let int_list = map read splitted_input :: [Int] -- [1,2,3,1,1,2,6,6,2]
    let set = Set.fromList int_list
    let result_list = Set.toList set -- [1,2,3,6]
    let tupleLists = toListofTuples result_list
    let result = toString tupleLists
    putStrLn result

import qualified Data.Set as S

splitfunc :: String -> [String] --C&P de StackOverflow: https://stackoverflow.com/questions/46580924/haskell-splitting-a-string-by-delimiter

splitfunc [] = [""]
splitfunc (c:cs) | c == ','  = "" : rest
             | otherwise = (c : head rest) : tail rest
    where rest = splitfunc cs

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((a,b):xs) n =
        if a-1 == n
            then ((n,b):xs)
            else [(n,n)] ++ ((a,b):xs)

convert :: [(Int,Int)] -> String
convert ((a,b):xs) =
    if null xs -- Si xs es null, no se agrega "," al final.
        then if a == b
                then show a
                else show a ++ "-" ++ show b
        else if a == b
                then show a ++ "," ++ convert(xs)
                else show a ++ "-" ++ show b ++ "," ++ convert(xs)
main :: IO()
main = do
 line <- getLine
 let linelist = splitfunc line  -- Str to Strlist
 let intlist = map(read::String->Int) linelist -- Strlist to Intlist
 let dataset = S.fromList intlist -- Intlist to Data.Set
 let settolist = S.toList dataset -- Data.set to List
 let finallist = foldl (flip (:)) [] settolist -- Descending order list
 let final = foldl group [] finallist
 let a_retornar = convert final
 putStrLn a_retornar

import qualified Data.List as List
import qualified Data.Set as Set
import Data.Function

--Se divide la palabra inicial en comas para generar una lista
dividirpalabra :: String -> Char -> [String]
dividirpalabra[] x = [""]
dividirpalabra (c:cs) x
  | c == x = "" : resto
  | otherwise = (c : head resto) : tail resto
  where
    resto = dividirpalabra cs x

--Se ordena la lista de numeros
ordenar = List.sortBy(compare`on`(read :: String -> Int))

--Funcion group que genera la lista con "-" entre si cuando hay paginas juntas
group :: [String] -> Int -> [String]
group []posicionprevia =[""]
group (x:xs)posicionprevia
    |posicion == posicionprevia =
      if xs == []
      then [x]
      else (if(posicionposterior /= succ posicion)
        then (x : resto)
        else ((x ++ head resto) : tail resto))
    |posicion == succ posicionprevia =
      if xs == []
      then ["-"++ x]
      else (if (posicionposterior /= succ posicion)
        then (("-"++ x) : resto)
        else resto)
    |otherwise =
      if xs == []
      then [x]
      else (if (posicionposterior /= succ posicion)
        then (x:resto)
        else (x ++ head resto) : tail resto)
      where
        posicion = (read x :: Int)
        posicionposterior = (read(head xs) :: Int)
        resto = group xs posicion

main = do
  numeros <- getLine
  let lista = dividirpalabra numeros ',' --Se obtiene la palabra y se quitan las comas
  let convertirlista = Set.fromList lista
  let elementos = Set.elems convertirlista
  let listaordenada = ordenar elementos --Se genera una lista ordenada con los numeros
  let listaordenada2 = group listaordenada(read(head listaordenada):: Int)
  let listafinal = List.intercalate "," listaordenada2 --Se genera una lista con las paginas juntas y luego se colocan las comas entre medio
  putStrLn listafinal

import Data.List (sort, intercalate, (\\))

main = do
  input <- getLine
  putStrLn $ fix input

wordsBy :: (Char -> Bool) -> String -> [String]
wordsBy p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsBy p s''
                            where (w, s'') = break p s'

delMults :: (Eq a) => [a] -> [a]
delMults []     = []
delMults (x:xs) = x : ( delMults $ dropWhile (==x) xs )

gather :: [Int] -> [[Int]]
gather [] = []
gather xs = a : gather (xs \\ a)
		where a = takeCont xs (head xs)

takeCont :: [Int] -> Int -> [Int]
takeCont []     n = []
takeCont (x:xs) n = if x==n then x : takeCont xs (n+1) else []

simplify :: (Show a) => [a] -> String
simplify [x] = show x
simplify xs  = (show . head) xs ++ "-" ++ (show . last) xs

fix :: String -> String
fix s = intercalate "," $ map simplify $ gather $ delMults $ sort $ map read $ wordsBy (==',') s

{-# OPTIONS_GHC -O2 -optc-O3 -optc-ffast-math -cpp #-}
{-# OPTIONS_GHC -funbox-strict-fields -fexcess-precision -monly-3-regs #-}
{-# LANGUAGE BangPatterns, OverloadedStrings, ScopedTypeVariables #-}

import Control.Applicative
import Control.Monad
-- import Control.Arrow
import Data.List
-- import Data.Maybe
import Data.Ord
-- import Data.Char
-- import Data.Function
-- import qualified Data.Map as Map
-- import qualified Data.Set as Set
import qualified Data.Foldable as F
import qualified Data.Traversable as T
-- import qualified Data.ByteString.Char8 as BS
import Text.Printf

main :: IO ()
main = do
  xs <- read . ("[" ++) . (++ "]") <$> getLine
  let n : ns = map head . group . sort $ xs :: [Int]
  let conv acc@(a, b) (c : cs)
        | b + 1 == c = conv (a, c) cs
        | otherwise  = acc : conv (c, c) cs
      conv acc [] = [acc]
      pages = conv (n , n) ns
      s = do
        (i, j) <- pages
        if i == j
          then printf "%d," i
          else printf "%d-%d," i j :: String
  printf "%s\n" (init s)

import qualified Data.Set as Set
import Data.List
--Funciones que me servirán para "limpiar" el input de la forma "1,2,3,44" a ["1","2","3","44"]
--y para pasar de "1-2" a ["1", "2"]
splitComma :: String -> [String]
splitComma s = let
  s2 =  map (\c -> if c==',' then ' ' else c) s
  in words s2
splitGuion :: String -> [String]
splitGuion s = let
    s2 =  map (\c -> if c=='-' then ' ' else c) s
    in words s2
--Función principal, itero con un foldl sobre el conjunto de números. Este conjunto está ordenado en contiene Ints.
--La idea es ir agregando uno por uno los elementos del Set a una lista
--Hay 3 casos principales de ingreso:
--1: Si la lista que retornará groupp está vacía, entonces llego e ingreso el valor
--2: Si no está vacía solo me interesará el último elemento, si este es de la forma "a" (y no "a-b") analizo si el elmento que
--   voy a ingresar es el sucesor de "a", si es el sucesor entonces modifico el ultimo de la lista por "a-i" donde i es el
--   número que voy a ingresar en esa iteración. Si no es el sucesor simplemente la lista crece pues agrego una nueva posición
--   de la forma "i" usando show.
--3: Si el último elemento de la lista es de la forma "a-b" entonces hago el splitGuion para obtener ["a", "b"] y analizar si
--   i es el sucesor de b, en ese caso modifico el último elemento por "a-i",de lo contrario la lista crece pues agrego una
--   nueva posición de la forma "i".
groupp :: [String] -> Int -> [String]
groupp list i
    |(length list == 0) = [show i]
    |(elem '-' (last list)) == True = if (splitGuion (last list)) !! 1 == show(pred i) then init list ++ [(splitGuion (last list) !! 0) ++ "-" ++ show i] else list ++ [show i]
    |otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]
main = do
  line <- getLine
  let splittedList = splitComma line --almaceno el input en una lista de la forma ["1","2","3","6"] por ejemplo
  let newList = [read a::Int | a <- splittedList] --paso los elementos de la lista a Int
  let mySet = Set.fromList newList --paso la lista a Set (quedan ordenados los elementos y además ordenados)
  let solution = foldl groupp [] mySet --obtengo la solución del problema pero en forma ["1-3","6"] por ejemplo
  let output1 = [a ++ ","| a <- (init solution)] --obtengo ["1-3,"]
  let output2 = output1 ++ [(last solution)] --agrego "6" y obtengo ["1-3,","6"]
  let output3 = foldl1 (++) output2 -- obtengo "1-3,6"
  putStrLn output3

--ghc problema1.hs -o problema1
-- ./problema1
import qualified Data.Set as Set
import Data.List
splitComma :: String -> [String]
splitComma s = let
  s2 =  map (\c -> if c==',' then ' ' else c) s
  in words s2
splitGuion :: String -> [String]
splitGuion s = let
    s2 =  map (\c -> if c=='-' then ' ' else c) s
    in words s2
groupp :: [String] -> Int -> [String]
groupp list i
    |(length list == 0) = [show i]
    |(elem '-' (last list)) == True = if (splitGuion (last list)) !! 1 == show(pred i) then init list ++ [(splitGuion (last list) !! 0) ++ "-" ++ show i] else list ++ [show i]
    |otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]
main = do
  line <- getLine
  let splittedList = splitComma line
  let newList = [read a::Int | a <- splittedList]
  let mySet = Set.fromList newList
  let solution = foldl groupp [] mySet
  let output1 = [a ++ ","| a <- (init solution)]
  let output2 = output1 ++ [(last solution)]
  let output3 = foldl1 (++) output2
  putStrLn output3

import qualified Data.Set as S
--import Data.List.Split (splitOn)
import Data.List (intercalate)

splitOn :: Char -> String -> [String]
splitOn r str = words [if c == r then ' ' else c | c <- str]

group :: [String] -> Int -> [String]
group [] i = [show i]
group (x:xs) i = if splitOn '-' x == [x] then
    if x == show (i-1)
        then (x ++ "-" ++ show i):xs
        else (show i):x:xs
    else let
        [x1,x2] = splitOn '-' x
        in if x2 == show (i-1)
            then (x1 ++ "-" ++ show i):xs
            else (show i):x:xs

listIt :: String -> IO String
listIt str = do
    let pageList = map read (splitOn ',' str) :: [Int]
    let pageSet = S.fromList pageList
    let ret = reverse (foldl group [] pageSet)
    return (intercalate "," ret)

main :: IO ()
main = do
    x <- getLine
    ret <- listIt x
    putStrLn ret

--import qualified Data.Set as Set
--import qualified Data.List.Split (splitOn)
import Data.List (sort,nub)
--import Data.Set (fromList)

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim
group :: [Int] -> Int -> [(Int,Int)]-- Este group lo que hace es entregar una lista de tuplas un numero y su siguiente ej 1 2 3 1 1 5 = [(1,3),(5,5)]
group x z = case x of
    [] -> []
    (y:ys) -> if y<=(z) then (group ys z)
            else [(y,siguiente_num x)] ++ (group ys (siguiente_num x))

siguiente_num :: [Int] -> Int
siguiente_num x = case x of
    [x]    ->  x
    (x:xs) ->  if ((x+1)==(head xs)) then (siguiente_num xs)
				else x
group_guion:: String -> (Int,Int) -> String-- este lo que hace es tomar la lista de group y escribirlo como el formato de salida
group_guion "" (x1,x2) = if x1 == x2 then show (x1)
    else show(x1)++"-"++show(x2)
group_guion palabra (x1,x2) = if x1 == x2 then palabra ++ ("," ++ show (x1))
    else palabra ++ ("," ++ show(x1)++"-"++show(x2))

main:: IO()
main = do
	rs <- getLine
	let lista_numero = sort (nub (map (read:: String -> Int ) (split rs ',')))
	--let conjunto = Set.fromList lista_numero
	let rangos = group lista_numero 0
	let rangos_string = foldl group_guion [] rangos
	putStrLn rangos_string

import qualified Data.Set as Set
import Data.List

stringSplit :: String -> Char -> [String]
stringSplit [] delim = [""]
stringSplit (c:cs) delim
	| c == delim = "" : rest
	| otherwise = (c : head rest) : tail rest
	where
			rest = stringSplit cs delim

groupp :: [String] -> Int -> [String]
groupp list i
	|(length list == 0) = [show i]
	|(elem '-' (last list)) == True = if (stringSplit (last list) '-') !! 1 == show(pred i) then init list ++ [((stringSplit (last list) '-') !! 0) ++ "-" ++ show i] else list ++ [show i]
	|otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]

main :: IO ()
main = do
	line <- getLine
	let list = stringSplit line ','
	let intList = map (read::String->Int) list
	let set = Set.fromList intList
	let setList = Set.toList set
	let solution = foldl groupp [] setList
	let output1 = [a ++ ","| a <- (init solution)]
	let output2 = output1 ++ [(last solution)]
	let output3 = foldl1 (++) output2
	putStrLn output3

import qualified Data.Set as Set

wordsWhen     :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
  "" -> []
  s' -> w : wordsWhen p s''
    where (w, s'') = break p s'

main = do
  input <- getLine
  let out = Set.fromList $ map (read::String->Int) (wordsWhen (==',') input)
  let out' = Set.foldl group ["",""] out
  if last (wordsWhen (==',')(head out')) == last out'
    then putStrLn $ head out'
    else putStrLn $ head out' ++ "-" ++ last out'

group :: [String] -> Int -> [String]
group acc x
  | acc == ["",""] = [show x, show x]
  | x == (read (last acc) :: Int) + 1 = [head acc, show x]
  | last (wordsWhen (==',') (head acc)) == last acc = [head acc ++ "," ++ show x, show x]
  | otherwise = [head acc ++ "-" ++ last acc ++ "," ++ show x, show x]

import qualified Data.Set as Set

-- Lista que retorna una tupla de boleanos.
-- Los boleanos indican si en la lista se encuentran los antecesores o sucesores de un numero
-- en la lista.
predSucc :: [Int] -> Int -> (Bool, Bool)
predSucc [] _ = (False, False)
predSucc (x:xs) e = if (((succ e) `elem` (x:xs)) && ((pred e) `elem` (x:xs))) then (True, True) else (if(((pred e) `elem` (x:xs))) then (True, False) else (if(((succ e) `elem` (x:xs))) then (False, True) else (False, False)))

printFinal :: [String] -> String
printFinal [] = ""
printFinal (x:xs) = if (('-' `elem` x) && ((length xs) > 0)) then ((x) ++ printFinal(xs)) else (if (x == "") then (("") ++ printFinal(xs)) else (if ((length xs) > 0) then ((x) ++ (",") ++ (printFinal(xs))) else (x ++ (printFinal(xs))) ))

boolText :: (Bool, Bool) -> Int -> String
boolText (True, True) x = ""
boolText (True, False) x = (show x)
boolText (False, True) x = (show x) ++ "-"
boolText (False, False) x =  (show x)

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'

group :: [Int] -> [String]
group (x:xs) = scanl (\a b -> (boolText (predSucc (x:xs) b) b) ) "" (x:xs)

main = do
    input <- getLine
    let listString = (wordsWhen (==',') input)
    let setInt = Set.fromList (map (read::String->Int) (listString))
    let listInt = Set.toList setInt
    putStrLn(printFinal (group listInt))

import qualified Data.Set as Set

group :: [Int] -> Int -> (Bool, Bool)
group [] _ = (False, False)
group (x:xs) e
    | (((succ e) `elem` (x:xs)) &&  ((pred e) `elem` (x:xs)))   = (True, True)
    | ((pred e) `elem` (x:xs))                                  = (True, False)
    | ((succ e) `elem` (x:xs))                                  = (False, True)
    | otherwise                                                 = (False, False)

groupList :: [Int] -> [(Bool, Bool)]
groupList (x:xs) = tail (scanl (\a b -> (group (x:xs) (fromIntegral b))) (False, False) (x:xs))

boolText :: [(Bool, Bool)] -> [Int] -> String
boolText [] [] = ""
boolText ((a, b):xs) (y:ys)
    | ((a == True) && (b == True))                      = "" ++ (boolText xs ys)
    | ((a == True) && (b == False) && (length ys) > 0)  = "-" ++ (show y) ++ "," ++ (boolText xs ys)
    | ((a == True) && (b == False) && (length ys) == 0) = "-" ++ (show y) ++ (boolText xs ys)
    | ((a == False) && (b == True))                     = (show y) ++ (boolText xs ys)
    | ((a == False) && (b == False) && (length ys) > 0) = (show y) ++ "," ++ (boolText xs ys)
    | otherwise                                         = (show y) ++ (boolText xs ys)

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'
main = do
    input <- getLine
    let listString = (wordsWhen (==',') input)
    let setInt = Set.fromList (map (read::String->Int) (listString))
    let listInt = Set.toList setInt
    putStrLn(boolText (groupList listInt) listInt)

import qualified Data.Set as Set

-- Función group, se le entrega una lista y un número, la función retorna una tupla de booleanos
-- Indicando si tiene predecesor o sucesor respectivamente.
group :: [Int] -> Int -> (Bool, Bool)
group [] _ = (False, False)
group (x:xs) e
    | (((succ e) `elem` (x:xs)) &&  ((pred e) `elem` (x:xs)))   = (True, True)
    | ((pred e) `elem` (x:xs))                                  = (True, False)
    | ((succ e) `elem` (x:xs))                                  = (False, True)
    | otherwise                                                 = (False, False)

-- Crea una lista de groups para todos los elementos.
groupList :: [Int] -> [(Bool, Bool)]
groupList (x:xs) = tail (scanl (\a b -> (group (x:xs) (fromIntegral b))) (False, False) (x:xs))

-- Convierte los datos entregados por groupList en texto para imprimirlo.
boolText :: [(Bool, Bool)] -> [Int] -> String
boolText [] [] = ""
boolText ((a, b):xs) (y:ys)
    | ((a == True) && (b == True))                      = "" ++ (boolText xs ys)
    | ((a == True) && (b == False) && (length ys) > 0)  = "-" ++ (show y) ++ "," ++ (boolText xs ys)
    | ((a == True) && (b == False) && (length ys) == 0) = "-" ++ (show y) ++ (boolText xs ys)
    | ((a == False) && (b == True))                     = (show y) ++ (boolText xs ys)
    | ((a == False) && (b == False) && (length ys) > 0) = (show y) ++ "," ++ (boolText xs ys)
    | otherwise                                         = (show y) ++ (boolText xs ys)

-- Función que splitea el texto (función proveída de un tercero en Stack Overflow ya que
-- splitOn no funciona en CodeForces).
wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'
main = do
    -- Obtiene el input
    input <- getLine

    -- Convierte el input en una lista de String, utilizando "," como separador.
    let listString = (wordsWhen (==',') input)

    -- Convierte la lista anterior en un conjunto de enteros.
    let setInt = Set.fromList (map (read::String->Int) (listString))

    -- Convierte el conjunto anterior en una lista de enteros
    let listInt = Set.toList setInt

    -- Aplico las funciones de arriba para obtener el texto correspondiente a la salida.
    let outPut = boolText (groupList listInt) (listInt)

    -- Imprime el texto en pantalla
    putStrLn(outPut)

import qualified Data.Set as Set
import qualified Data.List
import Data.List (nub,  sort)

{-crearlista :: [String] -> String
crearlista [] = []
crearlista (x:xs) = x++crearlista xs-}
--funcion que no sirvio para nada

condicion :: [String] -> Int -> [String]
condicion lista i
	|(length lista == 0) = [show i]
        |(elem '-' (last lista)) == True = if (split (last lista) '-') !! 1 == show(pred i) then init lista ++ [(split (last lista) '-' !! 0) ++ "-" ++ show i] else lista ++ [show i]
        |otherwise = if (last lista) == show(pred i) then init lista ++ [last lista ++ "-" ++ show i] else lista ++ [show i]

{-https://jmmv.dev/2006/08/split-function-in-haskell.html
split obtenido del link anterior-}

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
	| c == delim = "" : rest
        | otherwise = (c : head rest) : tail rest
        where
          rest = split cs delim

main :: IO()
main = do
	secuencia <- getLine
	let lista' = split secuencia ',' --elimino las comas
	let lista'' = sort (nub (map (read::String->Int) lista')) --ordeno los elementos de la lista
	let resultado = foldl condicion [] lista'' --recorro la lista de elmentos
	let resultado1 = [a ++ ","| a <- (init resultado)]
        let resultado2 = resultado1 ++ [(last resultado)]
        let resultado3 = foldl1 (++) resultado2
        putStrLn resultado3

import qualified Data.Set as Set
import qualified Data.List
import Data.List (nub,  sort)
{-https://jmmv.dev/2006/08/split-function-in-haskell.html
split obtenido del link anterior-}
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
	| c == delim = "" : rest
        | otherwise = (c : head rest) : tail rest
        where
          rest = split cs delim

grooup :: [String] -> Int -> [String]
grooup list i
	|(length list == 0) = [show i]
        |(elem '-' (last list)) == True = if (split (last list) '-') !! 1 == show(pred i) then init list ++ [(split (last list) '-' !! 0) ++ "-" ++ show i] else list ++ [show i]
        |otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]

main :: IO()
main = do
	secuencia <- getLine
	let lista = split secuencia ','
	let lista' = sort (nub (map (read::String->Int) lista))
	let resultado = foldl grooup [] lista'
	let resultado1 = [a ++ ","| a <- (init resultado)]
        let resultado2 = resultado1 ++ [(last resultado)]
        let resultado3 = foldl1 (++) resultado2
        putStrLn resultado3

import Data.List
import Data.Set
import System.IO

split :: String -> [String]
split [] = [""]
split (c:cs)
    | (c == ',')  = "" : resto
    | otherwise = (c : head resto) : tail resto
    where resto = Main.split cs

rangoDePaginas :: String -> Bool
rangoDePaginas "" = False
rangoDePaginas (x:xs)
    | (x == '-') = True
    | otherwise = rangoDePaginas xs

group :: [String] -> Int -> [String]
group pags x
    | pags == [] = [show x]
    | ((rangoDePaginas (head pags) == False) && ((read (head pags)) :: Int) + 1 == x) = [head pags ++ "-" ++ show x] ++ tail pags
    | ((rangoDePaginas (head pags) == False) && ((read (head pags)) :: Int) + 1 /= x) = [show x] ++ pags
    | ((rangoDePaginas (head pags) == True) && (n == x)) = [takeWhile (/='-') (head pags) ++ "-" ++ show x] ++ tail pags
    | ((rangoDePaginas (head pags) == True) && (n /= x)) = [show x] ++ pags
    where n = (read (tail (dropWhile (/='-') (head pags))) :: Int) + 1

pasarAInt :: [String] -> [Int]
pasarAInt [] = []
pasarAInt (x:xs) = (read x :: Int) : pasarAInt xs

main = do
    paginas <- getLine
    let lista = Main.split paginas
    let listaInt = pasarAInt lista
    let set = Data.Set.fromList listaInt
    let set2 = Data.Set.foldl Main.group [] set
    let set_final = Data.List.reverse set2
    let string = Data.List.intercalate "," set_final
    putStrLn string

import Data.List
import Data.Set
import System.IO

--Función que nos permite separar un string utilizando "," como separador y crea una lista con los strings resultantes
split :: String -> [String]
split [] = [""]
split (c:cs)
    | (c == ',')  = "" : resto
    | otherwise = (c : head resto) : tail resto
    where resto = Main.split cs

--Funcion que nos entrega True si es que el string contiene un "-", lo que representaria un rango de paginas
--Retorna False si es que es un unico numero correspondiente a la pagina
rangoDePaginas :: String -> Bool
rangoDePaginas "" = False
rangoDePaginas (x:xs)
    | (x == '-') = True
    | otherwise = rangoDePaginas xs

--Funcion que nos permite convertir una lista de strings a una lista de int
pasarAInt :: [String] -> [Int]
pasarAInt [] = []
pasarAInt (x:xs) = (read x :: Int) : pasarAInt xs

--Funcion que recibe un set de strings, agrega una pagina x de la manera que corresponda, y luego retorna el set correspondiente
--Es importante recalcar que cuando se agrega una nueva pagina, se agrega al principio del set, para reducir la complejidad temporal del problema
group :: [String] -> Int -> [String]
group pags x
    --Caso inicial, si es que no hay nada en el set, agrega la primera pagina
    | pags == [] = [show x]
    --En caso de que el primer elemento del set no sea un rango de paginas, hay dos opciones:
    --Si es que ademas la pagina x es la pagina que le sigue, se reemplaza por un string que represente un rango de paginas
    | ((rangoDePaginas (head pags) == False) && ((read (head pags)) :: Int) + 1 == x) = [head pags ++ "-" ++ show x] ++ tail pags
    --Si es que la pagina x no es la que le sigue, se agrega como nuevo elemento del set
    | ((rangoDePaginas (head pags) == False) && ((read (head pags)) :: Int) + 1 /= x) = [show x] ++ pags
    --En caso de que el primer elemento corresponda a un rango de paginas, tenemos otras dos opciones:
    --Si es que la pagina x, es la que le sigue a la pagina final del rango, se cambia por x
    | ((rangoDePaginas (head pags) == True) && (n == x)) = [takeWhile (/='-') (head pags) ++ "-" ++ show x] ++ tail pags
    --Si es que la pagina x no es la que le sigue a la pagina final del rango, se agrega como nuevo elemento del set
    | ((rangoDePaginas (head pags) == True) && (n /= x)) = [show x] ++ pags
    where n = (read (tail (dropWhile (/='-') (head pags))) :: Int) + 1

main = do
    paginas <- getLine
    let lista = Main.split paginas
    let listaInt = pasarAInt lista
    --Al utilizar la funcion fromList, convertimos la lista en un Data.Set y automaticamente se ordena
    let set = Data.Set.fromList listaInt
    --Se recorre el set y se le va aplicando la funcion group
    let set2 = Data.Set.foldl Main.group [] set
    --Como los nuevos elementos se agregan al principio del set resultante, ahora se invierte para que queden ordenados correctamente
    let set_final = Data.List.reverse set2
    --Se concatena el set de strings final poniendo una "," entre cada elemento
    let string_final = Data.List.intercalate "," set_final
    putStrLn string_final

import qualified Data.Set as S

main:: IO ()
main = do
    -- Se toma la linea como input
    linea <- getLine
    --putStrLn(linea)
    --Split por comas y nos da una lista
    --let x = splitOn "," linea
    --print x
    -- De string -> [String]
    let st = foldl split [] linea
    -- De [String] -> [Int]
    let xI = map read st :: [Int]
    --De conjunto a lista(se quitan los repetidos y se ordena )
    let xs = S.toList (S.fromList xI)
    --De [Int] a [String]
    --let xt = map show xs :: [String]
    --print xt
    --Se invierte la lista(mas eficiente)
    let r = reverse xs
    --Se crean una lista con tuplas(orden ascendente)
    let ivals = foldl addToIntervals [] r
    --print ivals
    let s = foldl intervalsToString [] ivals
    putStrLn s

addToIntervals :: [(Int,Int)] -> Int -> [(Int,Int)]
addToIntervals [] x = [(x,x)]
addToIntervals ((a,b):ivs) x =
    if x == a - 1
        then ((x,b):ivs)
        else ((x,x):(a,b):ivs)

intervalsToString :: String ->(Int,Int) -> String
intervalsToString "" (a,b) =
    if a == b
        then show (a)
        else show(a)++"-"++show(b)
intervalsToString ivs (a,b) =
    if a == b
        then ivs++(","++show (a))
        else ivs++(","++show(a)++"-"++show(b))

split:: [String]-> Char -> [String]
split [] c  = [[c]]
split [x] c =
    if c /= ','
        then [x++[c]]
        else [[],x]
split (x:xs) c =
    if c /= ','
        then (x++[c]):xs
        else []:x:xs

import Data.List hiding (foldl, group)

import Data.Set hiding (foldl)

main = do
    comando <- getLine
    let sincomas = wordsWhen (==',') comando
    let ordenado = ordenar sincomas
    let respuesta = foldl group [] ordenado
    let dar = reverse respuesta
    let solucion = sol False dar
    putStrLn solucion

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
    "" -> []
    s' -> w : wordsWhen p s''
        where (w, s'') = break p s'

ordenar :: [String] -> Set Int
ordenar lista = let
    temp = [read x :: Int | x <- lista]
    in fromList temp

group :: [String] -> Int -> [String]
group xs b
    | xs == [] = (show b):xs
    | b == ((read(head xs) :: Int) + 1) = show(b):"-":xs
    | otherwise = show(b):",":xs

sol :: Bool -> [String] -> String
sol True (a:b:as) = if b == "-" then sol True as else a ++ b ++ sol False as
sol False (a:b:as) = if b == "-" then a ++ b ++ sol True as else a ++ b ++ sol False as
sol a [b] = b

import List
main = interact (ans)
ans theInput = answer $ page a1 where
  line0 = head $ lines theInput
  split [] = []
  split x = y : if null z then [] else (split $ tail z) where
    (y,z) = break ( == ',') x
  a1 = sort $ map (read::String->Int) (split line0)
  page [x] = [(x,x)]
  page (x:xs) = if x==u || x+1==u then (x,v):ws else (x,x):(u,v):ws where
    (u,v):ws = page xs
  out (x,y) = if x==y then show x else (show x) ++ "-" ++ (show y)
  answer [(x,y)] = out (x,y)
  answer ((x,y):xs) = (out (x,y)) ++ "," ++ (answer xs)

import List
main = interact (ans)
ans theInput = answer $ page a1 where
  line0 = head $ lines theInput
  split [] = []
  split (',':xs) = split xs
  split x = (fst $ split1 x) : (split $ snd $ split1 x) where
    split1 x = break ( == ',') x
  a0 = map (read::String->Int) (split line0)
  a1 = sort a0
  page [x] = [(x,x)]
  page (x:xs) = if x==top || x+1==top
                   then (x,snd $ headPageXs):(tail pageXs)
                   else (x,x):pageXs
                    where
                      pageXs = page xs
                      headPageXs = head pageXs
                      top = fst headPageXs
  out (x,y) = if x==y then show x else (show x) ++ "-" ++ (show y)
  answer [(x,y)] = out (x,y)
  answer ((x,y):xs) = (out (x,y)) ++ "," ++ (answer xs)

import qualified Data.Set as S
import Data.List (nub, sort)

split' :: Char -> String -> [String]
split' x y = words [if c == x then ' ' else c | c <- y]

--FUNCIONES MALAS
{-}
group' :: [(Integer,Integer)] -> Integer -> [(Integer,Integer)]
group' (x:xs) y
    | snd(x)+1 == y =(snd(x),y)
    | fst(x) == 0 = (snd(x),snd(x))
    | otherwise = (0,y):x-}
{-
joinList :: [String] -> String
joinList [] = []
joinList (x:xs) = x++joinList xs-}

sec :: [Int] -> Int
sec x = case x of
    [x]    ->  x
    (x:xs) ->  if ((x+1)==(head xs)) then (sec xs) else x

group' :: [Int] -> Int -> [(Int,Int)]
group' x z = case x of
    [] -> []
    (y:ys) -> if y<=(z) then (group' ys z)
            else [(y,sec x)] ++ (group' ys (sec x))

joinHyphen :: String -> (Int,Int) -> String
joinHyphen "" (x,y)
    |x == y = show (x)
    |otherwise = show(x)++"-"++show(y)
joinHyphen z (x,y)
    |x == y = z++(","++show (x))
    |otherwise = z++(","++show(x)++"-"++show(y))

main :: IO()
main = do
    secuencia <- getLine
    --let list'= map digitToInt [ x | x <- secuencia, x/=',']
    let numbers = split' (',') secuencia
    let list'= sort (nub (map (read::String->Int) numbers))
    let groupSolution = group' list' 0
    let fin = foldl joinHyphen [] groupSolution
    putStrLn fin

import qualified Data.Set as S
import Data.List (nub, sort)

split' :: Char -> String -> [String]
split' r str = words [if c == r then ' ' else c | c <- str]

--FUNCIONES MALAS
{-}
group' :: [(Integer,Integer)] -> Integer -> [(Integer,Integer)]
group' (x:xs) y
    | snd(x)+1 == y =(snd(x),y)
    | fst(x) == 0 = (snd(x),snd(x))
    | otherwise = (0,y):x-}
{-}
joinList :: [String] -> String
joinList [] = []
joinList (x:xs) = x++joinList xs-}

secuencia :: [Int] -> Int
secuencia x = case x of
    [x]    ->  x
    (x:xs) ->  if ((x+1)==(head xs)) then (secuencia xs) else x

group' :: [Int] -> Int -> [(Int,Int)]
group' x z = case x of
    [] -> []
    (y:ys) -> if y<=(z) then (group' ys z)
            else [(y,secuencia x)] ++ (group' ys (secuencia x))

joinHyphen :: String -> (Int,Int) -> String
joinHyphen "" (x,y)
    |x == y = show (x)
    |otherwise = show(x)++"-"++show(y)
joinHyphen ivs (x,y)
    |x == y = ivs++(","++show (x))
    |otherwise = ivs++(","++show(x)++"-"++show(y))

main :: IO()
main = do
    secuencia <- getLine
    --let list'= map digitToInt [ x | x <- secuencia, x/=',']
    let numbers = split' (',') secuencia
    let list'= sort (nub (map (read::String->Int) numbers))
    let groupSolution = group' list' 0
    let fin = foldl joinHyphen [] groupSolution
    putStrLn fin

import qualified Data.Set as Set
import Data.String
import Data.List
import Control.Monad (mfilter)

main = do
  line <- getLine
  let lis = (sort . nub) (map (read::String->Int) (split ',' line)) --lis es la lista sin repetir y ordenada de numeros
  let pal = ""
  let ret = foldl grp pal lis
  if 'c' `elem` ret then putStrLn $ rc ret else putStrLn ret
  --print $ foldl grp pal lis

replace a b = map $ maybe b id . mfilter (/= a) . Just

--reemplazo el elemento que tenga c con el string que entre (c es para reconocer los numeros que vienen seguidos)
remp :: String -> String -> String
remp r st = intercalate "-" (filter (\s -> not ('c' `elem` s)) (split '-' st))++"-"++ r

--para remover un c final si es que la linea lo contiene
rc :: String -> String
rc str = filter (\s -> s /= 'c') str

split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s

--para obtener el valor numerico del numero
numb :: String -> Int
numb str = (read nun::Int) where
    nun = filter (\s -> s /= 'c') str

--funcion group
grp:: String -> Int -> String
grp "" x = ""++(show x)
grp str x =
    if length (foldl (\s x -> s ++ split ',' x) [] (split '-' str)) == 1
        then if (read str::Int) == x-1
                then str++"-"++(show x)++"c"
            else str++","++(show x)
    else do
        let ultim = (concat . (take 1 . reverse)) (foldl (\s x -> s ++ split ',' x) [] (split '-' str))
        if 'c' `elem` ultim
            then if (numb ultim) == (x-1)
                    then remp (show x ++"c") str
                else (replace 'c' ',' str)++(show x)
        else if (numb ultim) == (x-1)
                then str ++ "-" ++(show x)++"c"
            else str ++ "," ++(show x)

    import qualified Data.Set as Set
    import Data.List
--1.Lea correctamente los datos y almacene estos en un Data.Set
--2.Apoyado con su función, itere con un foldl sobre el Data.Set
    main :: IO ()
    main = do
--Ingreso cadena de paginas.
      input <- getLine
--Ayudandonos de nuestra funcion splitt nuestras paginas quedaran en una lista de strings.
      let paginas = splitt input ','
--Pasaremos los strings de nuestra lista creada anteriormente a enteros.  idea: http://zvon.org/other/haskell/Outputprelude/read_f.html
      let pagin = [read pag::Int | pag <- paginas]   --Recorre lista (pag) y transforma String->Int
--Como se solicita crearemos un Set con las paginas (ya pasadas a enteros en la lista) ingresadas .
      let pag = Set.fromList pagin
--Ayudandonos de nuestra funcion iteramos el set con foldl (funciona con el Set entregado y una lista vacia)  asi obtener nuestra solucion final.
      let final = foldl group1 [] pag
--Concatenaremos la primera parte hasta la coma
      let final1 = [a ++ ","| a <- (init final)]
--Agregamos el parametro solo en caso de haber y concatenamos con el anterior
      let finall = final1 ++ [(last final)]
-- String output
      let finalfinal = foldl1 (++) finall
      putStrLn finalfinal

 --Declaramos la funcion para separar los caracteres entregados. idea:https://jmmv.dev/2006/08/split-function-in-haskell.html
    splitt :: String -> Char -> [String]
    splitt [] delim = [""]
    splitt (c:cs) delim
      | c == delim = "" : rest
      | otherwise = (c : head rest) : tail rest
        where
          rest = splitt cs delim

--3.Implemente la función group :: a -> b -> a que lo va a ayudar para resolver el problema.
    group1 :: [String] -> Int -> [String]

    group1 lista elemento

      |(length lista == 0) = [show elemento]

      |(elem '-' (last lista)) == True = if (splitt (last lista) '-') !! 1 == show(pred elemento) then init lista ++ [(splitt (last lista) '-' !! 0) ++ "-" ++ show elemento] else lista ++ [show elemento]

      |otherwise = if (last lista) == show(pred elemento) then init lista ++ [last lista ++ "-" ++ show elemento] else lista ++ [show elemento]

    import qualified Data.Set as Set
    import Data.List
 --Declaramos la funcion para separar los caracteres entregados. idea:https://jmmv.dev/2006/08/split-function-in-haskell.html
    splitt :: String -> Char -> [String]
    splitt [] delim = [""]
    splitt (c:cs) delim
      | c == delim = "" : rest
      | otherwise = (c : head rest) : tail rest
        where
          rest = splitt cs delim

--3.Implemente la función group :: a -> b -> a que lo va a ayudar para resolver el problema.
    group1 :: [String] -> Int -> [String]

    group1 lista elemento

      |(length lista == 0) = [show elemento]

      |(elem '-' (last lista)) == True = if (splitt (last lista) '-') !! 1 == show(pred elemento) then init lista ++ [(splitt (last lista) '-' !! 0) ++ "-" ++ show elemento] else lista ++ [show elemento]

      |otherwise = if (last lista) == show(pred elemento) then init lista ++ [last lista ++ "-" ++ show elemento] else lista ++ [show elemento]

--1.Lea correctamente los datos y almacene estos en un Data.Set
--2.Apoyado con su función, itere con un foldl sobre el Data.Set
    main :: IO ()
    main = do
--Ingreso cadena de paginas.
      input <- getLine
--Ayudandonos de nuestra funcion splitt nuestras paginas quedaran en una lista de strings.
      let paginas = splitt input ','
--Pasaremos los strings de nuestra lista creada anteriormente a enteros.  idea: http://zvon.org/other/haskell/Outputprelude/read_f.html
      let pagin = [read pag::Int | pag <- paginas]   --Recorre lista (pag) y transforma String->Int
--Como se solicita crearemos un Set con las paginas (ya pasadas a enteros en la lista) ingresadas .
      let pag = Set.fromList pagin
--Ayudandonos de nuestra funcion iteramos el set con foldl (funciona con el Set entregado y una lista vacia)  asi obtener nuestra solucion final.
      let final = foldl group1 [] pag
--Concatenaremos la primera parte hasta la coma
      let final1 = [a ++ ","| a <- (init final)]
--Agregamos el parametro solo en caso de haber y concatenamos con el anterior
      let finall = final1 ++ [(last final)]
-- String output
      let finalfinal = foldl1 (++) finall
      putStrLn finalfinal

import System.IO
import System.Environment
import qualified Data.List as L
import qualified Data.Set as Set
main = do
  array_n <- getLine
  let list = buildList array_n
      intList = L.sort (Prelude.map read (Set.toList (Set.fromList list)) :: [Int])
      finalList = L.foldl groupNumbers [] intList
  putStrLn (L.intercalate "," (L.foldl format [] finalList))

buildList :: String -> [String]
buildList arr =
  if arr == "" then
    let args = [""] in args
  else do
    let newarr = split arr ',' in newarr

groupNumbers :: [[Int]]-> Int ->[[Int]]
groupNumbers [] n = [[n]]
groupNumbers [x] n =
  if n == (last x) + 1
    then
      let list = x ++ [n] in
        [list]
  else
    [x]++[[n]]
groupNumbers (x:xs) n =
  if n == (last x) + 1
    then
      let list = x ++ [n]
        in list:xs
  else
    let lists = x:(groupNumbers xs n) in lists

format :: [String] -> [Int] ->[String]
format s rango =
  if head rango == last rango
    then let r = show (head rango)
    in s++[r]
  else let r = show (head rango) ++ "-" ++ show (last rango)  in s++[r]

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

import qualified Data.Set as Set
import qualified Data.List as List

main = do
  line <- getLine
  let list = split line ','
  let set = Set.fromList list
  let pages = Set.elems set
  let sortedPages = List.sort pages
  let newPages = group sortedPages (read (head sortedPages) :: Int)
  let strPages = List.intercalate "," newPages
  putStrLn strPages

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [String] -> Int -> [String]
group [] posAnterior = [""]
group (x:xs) posAnterior
    | pos == posAnterior = if xs == [] then [x] else (if (nextPos /= succ pos) then (x : rest) else ((x ++ head rest) : tail rest))
    | pos == succ posAnterior = if xs == [] then ["-" ++ x] else (if (nextPos /= succ pos) then (("-" ++ x) : rest) else rest)
    | otherwise = if xs == [] then [x] else (if (nextPos /= succ pos) then (x : rest) else (x ++ head rest) : tail rest)
    where
      pos = (read x :: Int)
      nextPos = (read (head xs) :: Int)
      rest = group xs pos

import qualified Data.Set as Set

-- La funcion rep reemplaza todas las comas en el String dado por espacios.
rep :: String -> String
rep "" = ""
rep (',':xs) = " " ++ rep (xs)
rep (x:xs) = [x] ++ rep (xs)

-- La funcion group se encarga de construir el String deseado
group :: [String] -> Int -> [String]
group [] n = "-":(show n):[] --Si la lista esta vacia (Que siempre lo estara al inicio) se agrega la Int n como String y un guion.
group ("-":x:xs) n
    | (read x) == (pred n) = (show n):"-":restofList -- Si x es predecesor de n, se agrega n en la cabeza.
    | otherwise = "-":(show n):",":restofList -- En caso contrario, se reemplaza el guion por una coma, y se agrega n y un guion.
    where restofList = (x:xs)
group (x:xs) n
    | (read x) == (pred n) = (show n):xs -- Si x es predecesor de n, se reemplaza x por n.
    | otherwise = "-":(show n):",":x:xs -- En caso contrario, se agrega una coma, n y un guion.

-- Al terminar la funcion group la nueva lista puede contener un guion a la cabeza. Esta funcion lo elimina si esta presente.
eraseThing :: [String] -> [String]
eraseThing ("-":xs) = xs
eraseThing x = x

main :: IO ()
main = do
    line <- getLine
    let lineList = map (read :: String -> Int) ((words . rep) line) --Se usa rep y words para separar la String en una lista. Luego se usa map y read para convertirlo en una lista de Int
    let newSet = Set.fromList lineList --Se transforma la lista en Set
    let newList = foldl (group) [] newSet --Se utiliza foldl para construir la String con group, dando una lista vacia y el Set
    let groupLine = (concat . reverse) (eraseThing newList) --Se usa reverse y se concatena la lista, obteniendo el String deseado
    print (groupLine)

import qualified Data.Set as S

group :: [Char] -> Int -> [Char]
group "" num = "" ++ show num
group str num
    -- Si tenemos el sucesor, agregar '-' y luego el sucesor, se usa lenght para evitar problema con largo de lista en casos como "1,2"
    | succ (toInt(last str)) == num && length str == 1              = str ++ "-" ++ show num
    -- Si tenemos el sucesor y el peniultimo char es '-' cambiar el numero de la secuencia
    | succ (toInt(last str)) == num && last(init str) == '-'        = init str ++ show num
    -- Si tenemos el sucesor, agregar '-' y luego el numero
    | succ (toInt(last str)) == num                                 = str ++ "-" ++ show num
    -- Cualquier otro caso extender con ',' y el siguiente numero
    | otherwise                                                     = str ++ "," ++ show num

toInt :: Char -> Int
toInt c = read (c : []) :: Int

main = do
    name <- getLine
    let a = concatMap (\x -> if x == ',' then " " else [x]) name -- Remplazar comas por espacios para usar words
    let set = S.fromList (map read $ words a :: [Int]) --Set [1,2,3]
    --print (toInt (last "1-3,5-8") == 8)
    putStrLn (S.foldl group "" set)

import qualified Data.Set as S

group :: [Char] -> Int -> [Char]
group "" num = "" ++ show num
group str num
    -- Si tenemos el sucesor, agregar '-' y luego el sucesor, se usa lenght para evitar problema con largo de lista en casos como "1,2"
    | succ (toInt(last str)) == num && length str == 1              = str ++ "-" ++ show num
    -- Si tenemos el sucesor y el peniultimo char es '-' cambiar el numero de la secuencia
    | succ (toInt(last str)) == num && last(init str) == '-'        = init str ++ show num
    -- Si tenemos el sucesor, agregar '-' y luego el numero
    | succ (toInt(last str)) == num                                 = str ++ "-" ++ show num
    -- Cualquier otro caso extender con ',' y el siguiente numero
    | otherwise                                                     = str ++ "," ++ show num

toInt :: Char -> Int
toInt c = read (c : []) :: Int

main = do
    name <- getLine
    let a = concatMap (\x -> if x == ',' then " " else [x]) name -- Remplazar comas por espacios para usar words
    let set = S.fromList (map read $ words a :: [Int]) --Set [1,2,3]
    --print (toInt (last "1-3,5-8") == 8)
    print (S.foldl group "" set)

import qualified Data.List as List
import qualified Data.Set as Set

main :: IO()
main = do
 input <- getLine
 let inputList = split input ','
 let intList = map(read::String->Int) inputList
 let dataset = Set.fromList intList
 let dataSetList = Set.toList (Set.fromList intList)
 let flipList = foldl (flip (:)) [] dataSetList
 let lastList = foldl group [] flipList
 let returnList = showTuples lastList
 putStrLn returnList

--Fuente: https://stackoverflow.com/questions/47308280/haskell-list-of-int-tuples-to-string
showTuples :: [(Int, Int)] -> String
showTuples [] = ""
showTuples (x:[]) = show(fst(x)) ++ " " ++ show(snd(x))
showTuples (x:xs) = show(fst(x)) ++ " " ++ show(snd(x)) ++ " " ++ showTuples xs

--Fuente: https://jmmv.dev/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((x,y):xs) n
    |x-1 == n   = ((n,y):xs)
    |otherwise  = [(n,n)] ++ ((x,y):xs)

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 > 0 &&  null xs /= True) then show s1 ++ "-" ++ show s2 ++ "," else (if (s1 > 0 &&  null xs == True) then show s1 ++ "-" ++ show s2 else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) else (""))))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else(-k,-v) : grr t

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

pedirlista :: IO ()
pedirlista =
    putStrLn "Triate la lista"
    >> getLine
    >>= \x -> putStrLn ("Esta es tu lista " ++x)

reader :: [String] -> [Integer]
reader = map read
main = do
       rawdata <- getLine
       let ldata1 = split rawdata ','
       let ldata2 = reader ldata1
       let sdata = Set.fromList ldata2
       let ldata3 = Set.toList sdata
       let rango = gr ldata3
       let ns = grr ldata3
       let nss = groupon ns
       print ( nss )

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 > 0 &&  null xs /= True) then show s1 ++ "-" ++ show s2 ++ "," ++ groupon xs else (if (s1 > 0 &&  null xs == True) then show s1 ++ "-" ++ show s2 ++   groupon xs else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," ++  groupon xs else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs else show (s1*(-1)) ++  groupon xs)))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else(-k,-v) : grr t

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

pedirlista :: IO ()
pedirlista =
    putStrLn "Triate la lista"
    >> getLine
    >>= \x -> putStrLn ("Esta es tu lista " ++x)

reader :: [String] -> [Integer]
reader = map read
main = do
       rawdata <- getLine
       let ldata1 = split rawdata ','
       let ldata2 = reader ldata1
       let sdata = Set.fromList ldata2
       let ldata3 = Set.toList sdata
       let rango = gr ldata3
       let ns = grr ldata3
       let nss = groupon ns
       putStrLn nss

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
  | c == delim = "" : rest
  | otherwise = (c : head rest) : tail rest
  where
  rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 > 0 &&  null xs /= True) then show s1 ++ "-" ++ show s2 ++ "," ++ groupon xs else (if (s1 > 0 &&  null xs == True) then show s1 ++ "-" ++ show s2 ++   groupon xs else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," ++  groupon xs else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs else show (s1*(-1)) ++  groupon xs)))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else (if (k == v-1) then (k,v) : grr t else  (-k,-v) : grr t)

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

reader :: [String] -> [Integer]
reader = map read
main = do
    rawdata <- getLine
    let ldata1 = split rawdata ','
    let ldata2 = reader ldata1
    let sdata = Set.fromList ldata2
    let ldata3 = Set.toList sdata
    let rango = gr ldata3
    let ns = grr ldata3
    let nss = groupon ns
    putStrLn nss

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 > 0 &&  null xs /= True && s1 /= s2 -1  ) then show s1 ++ "-" ++ show s2 ++ "," ++ groupon xs else (if (s1 > 0 &&  null xs == True  && s1 /= s2 -1 ) then show s1 ++ "-" ++ show s2 ++   groupon xs else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," ++  groupon xs else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs else( if (s2==0) then show (s1*(-1)) ++  groupon xs else (if (null xs /= True) then show s1++","++show s2 ++ "," ++  groupon xs else ( show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs))))))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else(-k,-v) : grr t

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

pedirlista :: IO ()
pedirlista =
    putStrLn "Triate la lista"
    >> getLine
    >>= \x -> putStrLn ("Esta es tu lista " ++x)

reader :: [String] -> [Integer]
reader = map read
main = do
       rawdata <- getLine
       let ldata1 = split rawdata ','
       let ldata2 = reader ldata1
       let sdata = Set.fromList ldata2
       let ldata3 = Set.toList sdata
       let rango = gr ldata3
       let ns = grr ldata3
       let nss = groupon ns
       putStrLn nss

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 /= s2 -1  && s1 > 0 &&  null xs /= True  ) then show s1 ++ "-" ++ show s2 ++ "," ++ groupon xs else (if (s1 /= s2 -1 && s1 > 0 &&  null xs == True  ) then show s1 ++ "-" ++ show s2 ++   groupon xs else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," ++  groupon xs else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs else( if (s2==0) then show (s1*(-1)) ++  groupon xs else (if (null xs /= True) then show s1++","++show s2 ++ "," ++  groupon xs else ( show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs))))))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else(-k,-v) : grr t

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

pedirlista :: IO ()
pedirlista =
    putStrLn "Triate la lista"
    >> getLine
    >>= \x -> putStrLn ("Esta es tu lista " ++x)

reader :: [String] -> [Integer]
reader = map read
main = do
       rawdata <- getLine
       let ldata1 = split rawdata ','
       let ldata2 = reader ldata1
       let sdata = Set.fromList ldata2
       let ldata3 = Set.toList sdata
       let rango = gr ldata3
       let ns = grr ldata3
       let nss = groupon ns
       putStrLn nss

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 > 0 &&  null xs /= True) then show s1 ++ "-" ++ show s2 ++ "," else (if (s1 > 0 &&  null xs == True) then show s1 ++ "-" ++ show s2 else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) else (""))))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else(-k,-v) : grr t

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

pedirlista :: IO ()
pedirlista =
    putStrLn "Triate la lista"
    >> getLine
    >>= \x -> putStrLn ("Esta es tu lista " ++x)

reader :: [String] -> [Integer]
reader = map read
main = do
       rawdata <- getLine
       let ldata1 = split rawdata ','
       let ldata2 = reader ldata1
       let sdata = Set.fromList ldata2
       let ldata3 = Set.toList sdata
       let rango = gr ldata3
       let ns = grr ldata3
       let nss = groupon ns
       print ( ns )

import qualified Data.Set as Set
import qualified Data.Map as Map

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

groupon :: [(Integer,Integer)] -> String
groupon [] = ""
groupon ((s1,s2):xs) = if (s1 > 0 &&  null xs /= True) then show s1 ++ "-" ++ show s2 ++ "," ++ groupon xs else (if (s1 > 0 &&  null xs == True) then show s1 ++ "-" ++ show s2 ++   groupon xs else (if (s1 < 0 && s2 < 0 && null xs /= True) then show ((-1)*s1)++","++show ((-1)*s2)++"," ++  groupon xs else (if (s1 < 0 && s2 < 0 && null xs == True)  then show ((-1)*s1)++","++show ((-1)*s2) ++  groupon xs else "error" ++  groupon xs)))

gr :: [Integer] -> [(Integer,Integer)]
gr [] = []
gr [x] = [(x,0)]
gr (k:v:t) = (k,v) : gr t

grr :: [Integer] -> [(Integer,Integer)]
grr [] = []
grr [x] = [(-x,0)]
grr (k:v:t) = if (null t /= True) && (k ==  v - 1 ) && (v ==  head t - 1) then (k, shower t) : grr (drop (fromIntegral ( shower t - k - 1 )) t)  else(-k,-v) : grr t

shower :: [Integer] -> Integer
shower [x] = x
shower (k:t) = if (k == head t - 1  ) then shower t else k

pedirlista :: IO ()
pedirlista =
    putStrLn "Triate la lista"
    >> getLine
    >>= \x -> putStrLn ("Esta es tu lista " ++x)

reader :: [String] -> [Integer]
reader = map read
main = do
       rawdata <- getLine
       let ldata1 = split rawdata ','
       let ldata2 = reader ldata1
       let sdata = Set.fromList ldata2
       let ldata3 = Set.toList sdata
       let rango = gr ldata3
       let ns = grr ldata3
       let nss = groupon ns
       putStrLn nss

import qualified Data.Set as Set
import qualified Data.Map as Map

group :: [(Int, Int)] -> Int -> [(Int, Int)]
group [] p  = [(p, p)] --caso inicial
group pages p = let
    (p1,p2) = last pages

    in if p == p2 + 1 then (init pages) ++ [(p1,p)] else pages  ++ [(p,p)]

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
        | c == delim = "" : rest
        | otherwise = (c : head rest) : tail rest
    where
      rest = split cs delim

writer::[(Int, Int)] -> String
writer [] = ""
writer ((p1,p2):xs) = if p1 == p2 then show p1 ++ "," ++ writer xs else show p1 ++ "-" ++ show p2 ++ "," ++ writer xs

reader :: [String] -> [Int]
reader = map read

main :: IO ()
main = do
    rawdata <- getLine
    let ldata1 =split rawdata ','
    let ldata2 = reader ldata1
    let sdata = Set.fromList ldata2
    let ldata3 = Set.toList sdata
    let finalPages = foldl (group) [] ldata3
    putStrLn ( writer finalPages)

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]

grouping s [] _= s
grouping s (x:xs) flag= do
    if(flag)
        then if(lastNumber s ==(x-1))
            then grouping (init s ++ show x) xs True
            else grouping (s ++","++ show x++",") xs False
        else if(xs==[])
            then grouping (s++ show x) xs False
            else if(x==(head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]
grouping s [] _= s
grouping s (x:[]) _= do
    if(digitToInt (last s)==(x-1))
        then init s++ show x
        else s++ ","++ show x
grouping s (x:xs) flag= do
    if(flag)
        then if(digitToInt (last s)==(x-1))
            then grouping (init s ++ show x) xs True
            else grouping (s ++","++ show x) xs False
        else if( x== (head xs-1))
            then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
            else grouping ( s++ show x ++ ",") xs False

deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    print finalString

import System.IO
import Data.Char
import Data.List

groups :: [Char] -> Int -> [Char]
groups "" i = show i
groups palabra i = do
    if (lastSymbol 0 palabra=="-")
            then (init palabra)++[x|x<-show i, (lastNumber palabra+1)==i]++[x|x<-[last palabra ,',']++show i, (lastNumber palabra +1)/=i]
            else palabra++[x|x<-['-']++show i, (lastNumber palabra+1)==i]++[ x|x<-[',']++show i, (lastNumber palabra +1)/=i]

addComa::[Char]-> Int->[Char]
addComa palabra _ = [last palabra]++","

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int

lastSymbol:: Int->[Char]->[Char]
lastSymbol 0 s= lastSymbol 1 (reverse s)
lastSymbol 1 "" = ""
lastSymbol 1 (x:xs)= do
    if(isDigit x)
        then lastSymbol 1 xs
        else [x]
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main= do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= foldl groups "" sortedSet
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]
-- grouping "10,20," (30) False
grouping s [] _= s
-- grouping s (x:[]) flag= do
--     if(flag && digitToInt (last s)==(x-1))
--         then init s++ show x
--         else s++ ","++ show x
grouping s (x:xs) flag= do
    if(flag)
        then if(digitToInt (last s)==(x-1))
            then grouping (init s ++ show x) xs True
            else grouping (s ++","++ show x) xs False
        else if(xs==[])
            then grouping ( s++ show x) xs False
            else if(x== (head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

groups :: [Char] -> Int -> [Char]
groups "" i = show i
groups palabra i = do
    if (lastSymbol 0 palabra=="-")
            then (sinLastNumber palabra)++[x|x<-show i, (lastNumber palabra+1)==i]++[x|x<-[last palabra ,',']++show i, (lastNumber palabra +1)/=i]
            else palabra++[x|x<-['-']++show i, (lastNumber palabra+1)==i]++[ x|x<-[',']++show i, (lastNumber palabra +1)/=i]

addComa::[Char]-> Int->[Char]
addComa palabra _ = [last palabra]++","

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int

sinLastNumber::[Char]->[Char]
sinLastNumber s= reverse(dropWhile (isDigit) (reverse s))

lastSymbol:: Int->[Char]->[Char]
lastSymbol 0 s= lastSymbol 1 (reverse s)
lastSymbol 1 "" = ""
lastSymbol 1 (x:xs)= do
    if(isDigit x)
        then lastSymbol 1 xs
        else [x]
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main= do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= foldl groups "" sortedSet
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]

grouping s [] _= s
grouping s (x:xs) flag= do
    if(flag)
        then if(lastNumber s ==(x-1))
            then grouping (reverse (drop (length(show (lastNumber s))) (reverse s)) ++ show x) xs True
            else if(xs==[])
                then grouping (s ++"," ++show x) xs True
                else grouping (s ++","++ show x++",") xs False
        else if(xs==[])
            then grouping (s++ show x) xs False
            else if(x==(head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]

grouping s [] _= s
grouping s (x:xs) flag= do
    if(flag)
        then if(lastNumber s ==(x-1))
            then grouping (init s ++ show x) xs True
            else if(xs==[])
                then grouping (s ++"," ++show x) xs True
                else grouping (s ++","++ show x++",") xs False
        else if(xs==[])
            then grouping (s++ show x) xs False
            else if(x==(head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]
-- grouping "979,981,983-984" (987:[989,992,993,995,996,998,999,1000]) False
grouping s [] _= s
grouping s (x:xs) flag= do
    if(flag)
        then if(lastNumber s ==(x-1))
            then grouping (init s ++ show x) xs True
            else grouping (s ++","++ show x) xs False
        else if(xs==[])
            then grouping (s++ show x) xs False
            else if(x==(head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

groups :: [Char] -> Int -> [Char]
groups "" i = show i
groups palabra i = do
    if (lastSymbol 0 palabra=="-")
            then (sinLastNumber palabra)++[x|x<-show i, (lastNumber palabra+1)==i]++[x|x<-(show (lastNumber palabra)++[',']++show i), (lastNumber palabra +1)/=i]
            else palabra++[x|x<-['-']++show i, (lastNumber palabra+1)==i]++[ x|x<-[',']++show i, (lastNumber palabra +1)/=i]

addComa::[Char]-> Int->[Char]
addComa palabra _ = [last palabra]++","

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int

sinLastNumber::[Char]->[Char]
sinLastNumber s= reverse(dropWhile (isDigit) (reverse s))

lastSymbol:: Int->[Char]->[Char]
lastSymbol 0 s= lastSymbol 1 (reverse s)
lastSymbol 1 "" = ""
lastSymbol 1 (x:xs)= do
    if(isDigit x)
        then lastSymbol 1 xs
        else [x]
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main= do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    print sortedSet
    let finalString= foldl groups "" sortedSet
    putStrLn $ id finalString

import System.IO
import Data.Char
import Data.List

grouping :: [Char]->[Int] -> Bool-> [Char]

grouping s [] _= s
grouping s (x:xs) flag= do
    if(flag)
        then if(lastNumber s ==(x-1))
            then grouping (reverse (drop (length(show (lastNumber s))) (reverse s)) ++ show x) xs True
            else grouping (s++",") (x:xs) False
        else if(xs==[])
            then grouping (s++ show x) xs False
            else if(x==(head xs-1))
                then grouping (s++[y|y<-[','],length s >0 ,last s /= ',']++show x ++"-"++show (head xs)) (drop 1 xs) True
                else grouping ( s++ show x ++ ",") xs False

lastNumber:: [Char]->Int
lastNumber s= read (reverse(takeWhile (isDigit) (reverse s))) :: Int
deleteComas :: [Char] -> [Char]
deleteComas []= ""
deleteComas s = do
    if(isDigit (head s))
        then (take 1 s) ++ deleteComas (drop 1 s)
        else " " ++ deleteComas (drop 1 s)

main = do
    line<-getLine
    let listInt= map read $ words $deleteComas line :: [Int]
    let sortedSet = nub (sort listInt)
    let finalString= grouping "" sortedSet False
    print sortedSet
    putStrLn $ id finalString

import Data.List (sort)

main :: IO ()
main = getLine >>= putStrLn . drop 4 . solve (-1) (-1) . sort . read . ('[':) . (++"]")

solve :: Int -> Int -> [Int] -> String
solve k l [] | k + 1 < l = ',' : show k ++ '-' : show l
             | k + 1 == l = ',' : show k ++ ',' : show l
             | otherwise = ',' : show k
solve k l (x:xs) | l + 1 < x = solve k l [] ++ solve x x xs
                 | otherwise = solve k x xs

import qualified Data.Set as S

splitfunc :: String -> [String] --C&P de StackOverflow: https://stackoverflow.com/questions/46580924/haskell-splitting-a-string-by-delimiter

splitfunc [] = [""]
splitfunc (c:cs) | c == ','  = "" : rest
             | otherwise = (c : head rest) : tail rest
    where rest = splitfunc cs

group :: [(Int,Int)] -> Int -> [(Int,Int)]
group [] n = [(n,n)]
group ((a,b):xs) n =
    if b - 1 == n
	then ((n,a):xs) -- Se cambia a por n y b por a
        else [(n,n)] ++ ((a,b):xs)

convert :: [(Int,Int)] -> String
convert ((a,b):xs) =
    if null xs -- Si xs es null, no se agrega "," al final.
        then if a == b
                then show a
                else show a ++ "-" ++ show b
        else if a == b
                then show a ++ "," ++ convert(xs)
                else show a ++ "-" ++ show b ++ "," ++ convert(xs)
main :: IO()
main = do
 line <- getLine
 let linelist = splitfunc line
 let intlist = map(read::String->Int) linelist
 let dataset = S.fromList intlist
 let settolist = S.toList dataset
 let finallist = foldl (flip (:)) [] settolist -- Se da vuelta la lista, para trabajar con la cabeza
 let final = foldl group [] finallist

 do mapM_ print intlist
 do mapM_ print finallist
 let a = convert final
 putStrLn a

import qualified Data.Set as Set

splitComma :: String -> [String]
splitComma [] = [""]
splitComma (x:xs)
        | x == ',' = "" : splitComma xs
        | otherwise = (x : head rest) : tail rest
    where rest = splitComma xs

toString :: [(Int,Int)] -> String
toString [] = ""
toString ((a,b):xs)
    | a /= b = show a ++ "-" ++ show b ++ "," ++ toString xs
    | otherwise = if xs /= [] then show a ++ "," ++ toString xs else show a

toListofTuples :: [Int] -> [(Int,Int)]
toListofTuples [] = []
toListofTuples [a] = [(a,a)]
toListofTuples (a:b:xs)
    | a + 1 == b = (a , result) : toListofTuples new_list
    | otherwise = (a,a) : toListofTuples (b:xs)
    where result = maxN (b:xs) a
          new_list = filter (>result) (b:xs)

maxN :: [Int] -> Int -> Int
maxN (x:xs) a
    | xs == [] = a
    | a + 1 == x = maxN xs (a+1)
    | otherwise = a

main = do
    input <- getLine -- "1,2,3,1,1,2,6,6,2"
    let splitted_input = splitComma input
    let int_list = map read splitted_input :: [Int] -- [1,2,3,1,1,2,6,6,2]
    let set = Set.fromList int_list
    let result_list = Set.toList set -- [1,2,3,6]
    let tupleLists = toListofTuples result_list
    let result = toString tupleLists
    putStrLn result

import qualified Data.Set as Set

splitComma :: String -> [String]
splitComma [] = [""]
splitComma (x:xs)
        | x == ',' = "" : splitComma xs
        | otherwise = (x : head rest) : tail rest
    where rest = splitComma xs

toString :: [(Int,Int)] -> String
toString [] = ""
toString ((a,b):xs)
    | a /= b = show a ++ "-" ++ show b ++ "," ++ toString xs
    | otherwise = if xs /= [] then show a ++ "," ++ toString xs else show a

toListofTuples :: [Int] -> [(Int,Int)]
toListofTuples [] = []
toListofTuples [a] = [(a,a)]
toListofTuples (a:b:xs)
    | a + 1 == b = (a , result) : toListofTuples new_list
    | otherwise = (a,a) : toListofTuples (b:xs)
    where result = maxN (b:xs) a
          new_list = filter (>result) (b:xs)

maxN :: [Int] -> Int -> Int
maxN (x:xs) a
    | xs == [] = a
    | a + 1 == x = maxN xs (a+1)
    | otherwise = a

main = do
    input <- getLine -- "1,2,3,1,1,2,6,6,2"
    let splitted_input = splitComma input
    let int_list = map read splitted_input :: [Int] -- [1,2,3,1,1,2,6,6,2]
    let set = Set.fromList int_list
    let result_list = Set.toList set -- [1,2,3,6]
    let tupleLists = toListofTuples result_list
    let result = toString tupleLists
    print result

--ghc problema1.hs -o problema1
-- ./problema1
import qualified Data.Set as Set
import Data.List
splitComma :: String -> [String]
splitComma s = let
  s2 =  map (\c -> if c==',' then ' ' else c) s
  in words s2
splitGuion :: String -> [String]
splitGuion s = let
    s2 =  map (\c -> if c=='-' then ' ' else c) s
    in words s2
groupp :: [String] -> Int -> [String]
groupp list i
    |(length list == 0) = [show i]
    |(elem '-' (last list)) == True = if (splitGuion (last list)) !! 1 == show(pred i) then init list ++ [(splitGuion (last list) !! 0) ++ "-" ++ show i] else list ++ [show i]
    |otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]
main = do
  line <- getLine
  let splittedList = splitComma line
  let newList = [read a::Int | a <- splittedList]
  let mySet = Set.fromList newList
  let solution = foldl groupp [] mySet
  let output1 = [a ++ ","| a <- (init solution)]
  let output2 = output1 ++ [(last solution)]
  let output3 = foldl1 (++) output2
  print output3

import qualified Data.Set as Set
import Data.List

stringSplit :: String -> Char -> [String]
stringSplit [] delim = [""]
stringSplit (c:cs) delim
	| c == delim = "" : rest
	| otherwise = (c : head rest) : tail rest
	where
			rest = stringSplit cs delim

groupp :: [String] -> Int -> [String]
groupp list i
	|(length list == 0) = [show i]
	|(elem '-' (last list)) == True = if (stringSplit (last list) '-') !! 1 == show(pred i) then init list ++ [((stringSplit (last list) '-') !! 0) ++ "-" ++ show i] else list ++ [show i]
	|otherwise = if (last list) == show(pred i) then init list ++ [last list ++ "-" ++ show i] else list ++ [show i]

main :: IO ()
main = do
	line <- getLine
	let list = stringSplit line ','
	let intList = map (read::String->Int) list
	let set = Set.fromList intList
	let setList = Set.toList set
	let solution = foldl groupp [] setList
	let output1 = [a ++ ","| a <- (init solution)]
	let output2 = output1 ++ [(last solution)]
	let output3 = foldl1 (++) output2
	print output3

import qualified Data.Set as Set

wordsWhen     :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
  "" -> []
  s' -> w : wordsWhen p s''
    where (w, s'') = break p s'

main = do
  input <- getLine
  let out = Set.fromList $ wordsWhen (==',') input
  let out' = Set.foldl group ["",""] out
  if last (wordsWhen (==',')(head out')) == last out'
    then putStrLn $ head out'
    else putStrLn $ head out' ++ "-" ++ last out'

group :: [String] -> String -> [String]
group acc x
  | acc == ["",""] = [x,x]
  | (read x :: Integer) == (read (last acc) :: Integer) + 1 = [head acc, x]
  | last (wordsWhen (==',') (head acc)) == last acc = [head acc ++ "," ++ x, x]
  | otherwise = [head acc ++ "-" ++ last acc ++ "," ++ x, x]

import qualified Data.Set as Set

group :: [Int] -> Int -> (Bool, Bool)
group [] _ = (False, False)
group (x:xs) e
    | (((succ e) `elem` (x:xs)) &&  ((pred e) `elem` (x:xs)))   = (True, True)
    | ((pred e) `elem` (x:xs))                                  = (True, False)
    | ((succ e) `elem` (x:xs))                                  = (False, True)
    | otherwise                                                 = (False, False)

groupList :: [Int] -> [(Bool, Bool)]
groupList (x:xs) = tail (scanl (\a b -> (group (x:xs) (fromIntegral b))) (False, False) (x:xs))

boolText :: [(Bool, Bool)] -> [Int] -> String
boolText [] [] = ""
boolText ((a, b):xs) (y:ys)
    | ((a == True) && (b == True))                      = "" ++ (boolText xs ys)
    | ((a == True) && (b == False) && (length ys) > 0)  = "-" ++ (show y) ++ "," ++ (boolText xs ys)
    | ((a == True) && (b == False) && (length ys) == 0) = "-" ++ (show y) ++ (boolText xs ys)
    | ((a == False) && (b == True))                     = (show y) ++ (boolText xs ys)
    | ((a == False) && (b == False) && (length ys) > 0) = (show y) ++ "," ++ (boolText xs ys)
    | otherwise                                         = (show y) ++ (boolText xs ys)

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'
main = do
    input <- getLine
    let listString = (wordsWhen (==',') input)
    let setInt = Set.fromList (map (read::String->Int) (listString))
    let listInt = Set.toList setInt
    putStrLn(show (boolText (groupList listInt) listInt))

import qualified Data.Set as Set

-- Lista que retorna una tupla de boleanos.
-- Los boleanos indican si en la lista se encuentran los antecesores o sucesores de un numero
-- en la lista.
predSucc :: [Int] -> Int -> (Bool, Bool)
predSucc [] _ = (False, False)
predSucc (x:xs) e = if (((succ e) `elem` (x:xs)) && ((pred e) `elem` (x:xs))) then (True, True) else (if(((pred e) `elem` (x:xs))) then (True, False) else (if(((succ e) `elem` (x:xs))) then (False, True) else (False, False)))

printFinal :: [String] -> String
printFinal [] = ""
printFinal (x:xs) = if (('-' `elem` x) && ((length xs) > 0)) then ((x) ++ printFinal(xs)) else (if (x == "") then (("") ++ printFinal(xs)) else (if ((length xs) > 0) then ((x) ++ (",") ++ (printFinal(xs))) else (x ++ (printFinal(xs))) ))

boolText :: (Bool, Bool) -> Int -> String
boolText (True, True) x = ""
boolText (True, False) x = (show x)
boolText (False, True) x = (show x) ++ "-"
boolText (False, False) x =  (show x)

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'

group :: [Int] -> [String]
group (x:xs) = scanl (\a b -> (boolText (predSucc (x:xs) b) b) ) "" (x:xs)

main = do
    input <- getLine
    let listString = (wordsWhen (==',') input)
    let setInt = Set.fromList (map (read::String->Int) (listString))
    let listInt = Set.toList setInt
    print(printFinal (group listInt))

import qualified Data.Set as Set

-- Lista que retorna una tupla de boleanos.
-- Los boleanos indican si en la lista se encuentran los antecesores o sucesores de un numero
-- en la lista.
predSucc :: [Int] -> Int -> (Bool, Bool)
predSucc [] _ = (False, False)
predSucc (x:xs) e = if (((succ e) `elem` (x:xs)) && ((pred e) `elem` (x:xs))) then (True, True) else (if(((pred e) `elem` (x:xs))) then (True, False) else (if(((succ e) `elem` (x:xs))) then (False, True) else (False, False)))

printFinal :: [String] -> String
printFinal [] = ""
printFinal (x:xs) = if (('-' `elem` x) && ((length xs) > 0)) then ((x) ++ printFinal(xs)) else (if (x == "") then (("") ++ printFinal(xs)) else (if ((length xs) > 0) then ((x) ++ (", ") ++ (printFinal(xs))) else (x ++ (printFinal(xs))) ))

boolText :: (Bool, Bool) -> Int -> String
boolText (True, True) x = ""
boolText (True, False) x = (show x)
boolText (False, True) x = (show x) ++ "-"
boolText (False, False) x =  (show x)

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
                      "" -> []
                      s' -> w : wordsWhen p s''
                            where (w, s'') = break p s'

group :: [Int] -> [String]
group (x:xs) = scanl (\a b -> (boolText (predSucc (x:xs) b) b) ) "" (x:xs)

main = do
    input <- getLine
    let listString = (wordsWhen (==',') input)
    let setInt = Set.fromList (map (read::String->Int) (listString))
    let listInt = Set.toList setInt
    print(printFinal (group listInt))

import Data.List
import Data.Set
import System.IO

split :: String -> [String]
split [] = [""]
split (c:cs)
    | (c == ',')  = "" : resto
    | otherwise = (c : head resto) : tail resto
    where resto = Main.split cs

rangoDePaginas :: String -> Bool
rangoDePaginas "" = False
rangoDePaginas (x:xs)
    | (x == '-') = True
    | otherwise = rangoDePaginas xs

group :: [String] -> Int -> [String]
group pags x
    | pags == [] = [show x]
    | ((rangoDePaginas (head pags) == False) && ((read (head pags)) :: Int) + 1 == x) = [head pags ++ "-" ++ show x] ++ tail pags
    | ((rangoDePaginas (head pags) == False) && ((read (head pags)) :: Int) + 1 /= x) = [show x] ++ pags
    | ((rangoDePaginas (head pags) == True) && (n == x)) = [takeWhile (/='-') (head pags) ++ "-" ++ show x] ++ tail pags
    | ((rangoDePaginas (head pags) == True) && (n /= x)) = [show x] ++ pags
    where n = (read (tail (dropWhile (/='-') (head pags))) :: Int) + 1

pasarAInt :: [String] -> [Int]
pasarAInt [] = []
pasarAInt (x:xs) = (read x :: Int) : pasarAInt xs

main = do
    paginas <- getLine
    let lista = Main.split paginas
    putStrLn $ show lista
    let listaInt = pasarAInt lista
    let set = Data.Set.fromList listaInt
    let set2 = Data.Set.foldl Main.group [] set
    let set_final = Data.List.reverse set2
    let string = Data.List.intercalate "," set_final
    putStrLn string

import qualified Data.Set as S

main:: IO ()
main = do
    -- Se toma la linea como input
    linea <- getLine
    --putStrLn(linea)
    --Split por comas y nos da una lista
    --let x = splitOn "," linea
    --print x
    -- de string -> [String]
    let st = foldl split [] linea
    --De conjunto a lista(se quitan los repetidos y se ordena )
    --print st
    let xs = S.toList (S.fromList st)
    --De [String] a [Int]
    let xI = map read xs :: [Int]
    --Se invierte la lista(mas eficiente)
    let r = reverse xI
    --print r
    --Se crean una lista con tuplas(orden ascendente)
    let ivals = foldl addToIntervals [] r
    --print ivals
    let s = foldl intervalsToString [] ivals
    print s

addToIntervals :: [(Int,Int)] -> Int -> [(Int,Int)]
addToIntervals [] x = [(x,x)]
addToIntervals ((a,b):ivs) x =
    if x == a - 1
        then ((x,b):ivs)
        else ((x,x):(a,b):ivs)

intervalsToString :: String ->(Int,Int) -> String
intervalsToString "" (a,b) =
    if a == b
        then show (a)
        else show(a)++"-"++show(b)
intervalsToString ivs (a,b) =
    if a == b
        then ivs++(","++show (a))
        else ivs++(","++show(a)++"-"++show(b))

split:: [String]-> Char -> [String]
split [] c  = [[c]]
split [x] c =
    if c /= ','
        then [x++[c]]
        else [[],x]
split (x:xs) c =
    if c /= ','
        then (x++[c]):xs
        else []:x:xs

import qualified Data.Set as S

main:: IO ()
main = do
    -- Se toma la linea como input
    linea <- getLine
    --putStrLn(linea)
    --Split por comas y nos da una lista
    --let x = splitOn "," linea
    --print x
    -- de string -> [String]
    let st = foldl split [] linea
    --De conjunto a lista(se quitan los repetidos y se ordena )
    --print st
    let xs = S.toList (S.fromList st)
    --De [String] a [Int]
    let xI = map read xs :: [Int]
    --Se invierte la lista(mas eficiente)
    let r = reverse xI
    --print r
    --Se crean una lista con tuplas(orden ascendente)
    let ivals = foldl addToIntervals [] r
    --print ivals
    let s = foldl intervalsToString [] ivals
    putStrLn s

addToIntervals :: [(Int,Int)] -> Int -> [(Int,Int)]
addToIntervals [] x = [(x,x)]
addToIntervals ((a,b):ivs) x =
    if x == a - 1
        then ((x,b):ivs)
        else ((x,x):(a,b):ivs)

intervalsToString :: String ->(Int,Int) -> String
intervalsToString "" (a,b) =
    if a == b
        then show (a)
        else show(a)++"-"++show(b)
intervalsToString ivs (a,b) =
    if a == b
        then ivs++(","++show (a))
        else ivs++(","++show(a)++"-"++show(b))

split:: [String]-> Char -> [String]
split [] c  = [[c]]
split [x] c =
    if c /= ','
        then [x++[c]]
        else [[],x]
split (x:xs) c =
    if c /= ','
        then (x++[c]):xs
        else []:x:xs

import Data.List hiding (foldl, group)

import Data.Set hiding (foldl)

main = do
    comando <- getLine
    let sincomas = wordsWhen (==',') comando
    let ordenado = ordenar sincomas
    let respuesta = foldl group [] ordenado
    let dar = reverse respuesta
    let solucion = sol False dar
    print solucion

wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s =  case dropWhile p s of
    "" -> []
    s' -> w : wordsWhen p s''
        where (w, s'') = break p s'

ordenar :: [String] -> Set Int
ordenar lista = let
    temp = [read x :: Int | x <- lista]
    in fromList temp

group :: [String] -> Int -> [String]
group xs b
    | xs == [] = (show b):xs
    | b == ((read(head xs) :: Int) + 1) = show(b):"-":xs
    | otherwise = show(b):",":xs

sol :: Bool -> [String] -> String
sol True (a:b:as) = if b == "-" then sol True as else a ++ b ++ sol False as
sol False (a:b:as) = if b == "-" then a ++ b ++ sol True as else a ++ b ++ sol False as
sol a [b] = b

import qualified Data.Set as Set
import Data.String
import Data.List
import Control.Monad (mfilter)

main = do
  line <- getLine
  let lis = (sort . nub) (map (read::String->Int) (split ',' line)) --lis es la lista sin repetir y ordenada de numeros
  let pal = ""
  let ret = foldl grp pal lis
  if 'c' `elem` ret then print $ rc ret else print ret
  --print $ foldl grp pal lis

replace a b = map $ maybe b id . mfilter (/= a) . Just

--reemplazo el elemento que tenga c con el string que entre (c es para reconocer los numeros que vienen seguidos)
remp :: String -> String -> String
remp r st = intercalate "-" (filter (\s -> not ('c' `elem` s)) (split '-' st))++"-"++ r

--para remover un c final si es que la linea lo contiene
rc :: String -> String
rc str = filter (\s -> s /= 'c') str

split :: Eq a => a -> [a] -> [[a]]
split d [] = []
split d s = x : split d (drop 1 y) where (x,y) = span (/= d) s

--para obtener el valor numerico del numero
numb :: String -> Int
numb str = (read nun::Int) where
    nun = filter (\s -> s /= 'c') str

--funcion group
grp:: String -> Int -> String
grp "" x = ""++(show x)
grp str x =
    if length (foldl (\s x -> s ++ split ',' x) [] (split '-' str)) == 1
        then if (read str::Int) == x-1
                then str++"-"++(show x)++"c"
            else str++","++(show x)
    else do
        let ultim = (concat . (take 1 . reverse)) (foldl (\s x -> s ++ split ',' x) [] (split '-' str))
        if 'c' `elem` ultim
            then if (numb ultim) == (x-1)
                    then remp (show x ++"c") str
                else (replace 'c' ',' str)++(show x)
        else if (numb ultim) == (x-1)
                then str ++ "-" ++(show x)++"c"
            else str ++ "," ++(show x)

import System.IO
import System.Environment
import qualified Data.List as L
import qualified Data.Set as Set
main = do
  array_n <- getLine
  let list = buildList array_n
      intList = L.sort (Prelude.map read (Set.toList (Set.fromList list)) :: [Int])
      finalList = L.foldl groupNumbers [] intList
  print (L.intercalate ", " (L.foldl format [] finalList))

buildList :: String -> [String]
buildList arr =
  if arr == "" then
    let args = [""] in args
  else do
    let newarr = split arr ',' in newarr

groupNumbers :: [[Int]]-> Int ->[[Int]]
groupNumbers [] n = [[n]]
groupNumbers [x] n =
  if n == (last x) + 1
    then
      let list = x ++ [n] in
        [list]
  else
    [x]++[[n]]
groupNumbers (x:xs) n =
  if n == (last x) + 1
    then
      let list = x ++ [n]
        in list:xs
  else
    let lists = x:(groupNumbers xs n) in lists

format :: [String] -> [Int] ->[String]
format s rango =
  if head rango == last rango
    then let r = show (head rango)
    in s++[r]
  else let r = show (head rango) ++ "-" ++ show (last rango)  in s++[r]

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim

import System.IO
import System.Environment
import qualified Data.List as L
import qualified Data.Set as Set
main = do
  array_n <- getLine
  let list = buildList array_n
      intList = L.sort (Prelude.map read (Set.toList (Set.fromList list)) :: [Int])
      finalList = L.foldl groupNumbers [] intList
  putStrLn (L.intercalate ", " (L.foldl format [] finalList))

buildList :: String -> [String]
buildList arr =
  if arr == "" then
    let args = [""] in args
  else do
    let newarr = split arr ',' in newarr

groupNumbers :: [[Int]]-> Int ->[[Int]]
groupNumbers [] n = [[n]]
groupNumbers [x] n =
  if n == (last x) + 1
    then
      let list = x ++ [n] in
        [list]
  else
    [x]++[[n]]
groupNumbers (x:xs) n =
  if n == (last x) + 1
    then
      let list = x ++ [n]
        in list:xs
  else
    let lists = x:(groupNumbers xs n) in lists

format :: [String] -> [Int] ->[String]
format s rango =
  if head rango == last rango
    then let r = show (head rango)
    in s++[r]
  else let r = show (head rango) ++ "-" ++ show (last rango)  in s++[r]

split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
    | c == delim = "" : rest
    | otherwise = (c : head rest) : tail rest
    where
        rest = split cs delim