Haskell: проблема с рекурсией - PullRequest
1 голос
/ 16 марта 2011

Я пытаюсь отформатировать текст в форме прямоугольника; в настоящее время я смог правильно выровнять его по левому краю, но последняя строка не простирается настолько далеко, насколько это возможно.

Я пытаюсь рассчитать оптимальную ширину поля, чтобы минимизировать или полностью удалить ее.

Я полностью застрял. Код ниже показывает соответствующие функции. На данный момент он застрял в бесконечном цикле. Куда я иду не так?

Кстати, какой лучший способ отладки кода на Haskell? (Да, я очень новичок в этом.)

optimFieldWidth должен сравнивать длины строк до тех пор, пока длина верхней строки не будет равна длине нижней строки, а затем возвращать ширину поля, что приводит к истинности этого значения.

module Main where

import System
import Data.List

main = do 
  (f:_) <- getArgs
  xs <- getContents
  putStr (show (bestFieldWidth maxLineLength xs))

bestFieldWidth :: Int -> String -> Int
bestFiledWidth _ [] = 0
bestFieldWidth lineLength xs
  | length (last input) == length (head input) = lineLength
  | otherwise = bestFieldWidth (length (head (rect (lineLength-1) xs))) xs
  where input = lines xs

rect :: Int -> String -> [String]
rect _ [] = []
rect lineLength xs
  | length input <= len = [input]
  | otherwise           = take len input : rect len (drop len input)
  where input = trim xs
        len   = bestFieldWidth lineLength xs

maxLineLength :: Int
maxLineLength = 40

Все ответы приветствуются. Спасибо.

Ответы [ 3 ]

1 голос
/ 18 марта 2011

Я думал, что поставлю фактическое решение здесь на тот случай, если другие психиатры захотят это сделать. Пожалуйста, имейте в виду, что это было написано идиотом, так что это, вероятно, не самое элегантное решение.

maxFieldWidth :: Int
maxFieldWidth = 30

rect :: String -> String
rect xs  = (unlines (chunk (bestFieldWidth (maxFieldWidth) (lines input)) input))
  where input = itemsReplace '\n' ' ' xs

--Should be called with the point maximum desired width as n
bestFieldWidth :: Int -> [String] -> Int
bestFieldWidth _ [] = error "bestFieldWidth: Empty List"
bestFieldWidth n xs
  | n == 6 = 6
  | 1 == (length (last input)) = n
  | otherwise = (bestFieldWidth (n-1) xs)
  where input = chunk n (unlines xs)

chunk :: Int -> [a] -> [[a]]
chunk n [] = []
chunk n xs = ys : chunk n zs
  where (ys,zs) = splitAt n xs

itemsReplace :: Eq a => a -> a -> [a] -> [a]
itemsReplace _ _ [] = []
itemsReplace c r (x:xs)
  | c == x    = r:itemsReplace c r xs
  | otherwise = x:itemsReplace c r xs
0 голосов
/ 17 марта 2011

В ответ на ваше примечание, вот отличное руководство по отладке Haskell: http://cgi.cse.unsw.edu.au/~dons/blog/2007/11/14

Есть также Debug.Trace, который позволяет вставлять операторы печати.Конечно, его следует использовать только во время отладки, потому что это дает вашей функции побочные эффекты.

http://hackage.haskell.org/packages/archive/base/latest/doc/html/Debug-Trace.html

0 голосов
/ 16 марта 2011

Кажется, что условие length (last input) == length (head input) один раз ложно никогда не сбывается в последующих вызовах area, таким образом, заставляя эту функцию всегда принимать ветвь otherwise и продолжать вызывать себя бесконечно с одинаковыми значениями xs input.

Возможная причина этого заключается в том, что вы используете функцию lines, которая разбивает строку с символами новой строки таким образом, что не зависит от lineLength и не согласуется с вашим разделением строк в функции rect.

...