Skip to content

Instantly share code, notes, and snippets.

@pqr
Created September 3, 2014 12:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pqr/963eef53c3a52793edcb to your computer and use it in GitHub Desktop.
Save pqr/963eef53c3a52793edcb to your computer and use it in GitHub Desktop.
module Main where
{- программа на Haskell для статьи http://pqr7.wordpress.com/2014/09/03/haskell-vs-php/ -}
import qualified Data.Text as T --
import Data.List
parse :: String -> [[String]]
parse text = splitPerBlocks $ getLines text
getLines :: String -> [String]
getLines text = map trim $ splitLines text
where trim = T.unpack . T.strip
splitLines text1 = T.splitOn (T.pack "\n") $ T.pack text1
splitPerBlocks :: [String] -> [[String]]
splitPerBlocks = splitPerBlocksRecursiveFold []
splitPerBlocksRecursiveFold :: [[String]] -> [String] -> [[String]]
splitPerBlocksRecursiveFold blocks lns
| length lns < 20 = blocks
| length linesWithoutHeaderAndFlag >= 20 = let first20Lines = take 20 linesWithoutHeaderAndFlag
otherLines = drop 20 linesWithoutHeaderAndFlag
newFoundBlocks = blocks ++ [first20Lines]
in splitPerBlocksRecursiveFold newFoundBlocks otherLines
| otherwise = blocks
where linesWithoutHeaderAndFlag = dropFlagLine . dropHeaderLine $ lns
dropHeaderLine :: [String] -> [String]
dropHeaderLine lns
| isInfixOf "Container No." $ head lns = tail lns
| otherwise = lns
dropFlagLine :: [String] -> [String]
dropFlagLine lns
| length lns <= 20 = lns
| isInfixOf "Flag:" $ lns !! 20 = take 20 lns ++ drop 21 lns
| otherwise = lns
main = do
s <- getContents
print $ length $ parse s
@Maru1337
Copy link

Maru1337 commented Sep 10, 2016

Сразу заметно, что ты похапе погромист.

Кроме того, что это самый лютый говнокод, который я видел в своей жизни, он еще и самый бесполезный. Потому что он, по сути, не делает ничего. Хаскель - ленивый язык, поэтому вторая строка в main, для того чтобы вывести результат length, не станет вычислять содержимое в листе, который получается на выходе parse s, а всего лишь посчитает его длину. Говоря более техническим языком, length вычисляет свой аргумент до weak head normal form.

Проверить ты это можешь, заменив мейн на, например:

m2 = do
  s <- readFile "txt"
  let ps = parse s
  print $ length ps
  return ps

для честности эксперимента, а затем вызвав её в ghci вот так:

λ> x <- m2
20
λ> :sprint x
x = [,,,,,,,,,,,,,,,,,,,]

Про тип стринг и IO техт-модуля я даже не говорю, пушо это уже совсем темный лес будет, походу.
Ну и не-дцп версия этого кода займет строчек 10 от силы, но продемострировать её я не могу, поскольку ТЗ так и не было толком описано, а дешифровать его из этой простыни криптокода не представляется возможным.

@Maru1337
Copy link

Maru1337 commented Sep 11, 2016

{-# LANGUAGE OverloadedStrings #-}
import           Data.List.Split
import qualified Data.Text.Lazy    as TL
import qualified Data.Text.Lazy.IO as XL
main :: IO ()
main =
  map TL.strip .TL.lines <$> XL.readFile "in.txt" >>=
   XL.writeFile "out.txt" .TL.unlines .concatMap (TL.replicate 50 "-":)
   .checklast .chunksOf 20 .filter shit >> putStrLn "Done!"
  where shit l       = not .or $ map (`TL.isInfixOf` l) [ "Container No.","Flag:" ]
        checklast xs = if 20 > length (last xs) then init xs else xs

Вроде бы вот так. Ну только аут в файл и блоки явно поделены, чтобы визуально понятно было.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment