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 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 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 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

-- 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

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)

    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

-- 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 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 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.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.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.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.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

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
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 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 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.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 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
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

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
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 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 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 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