2016-09-17 7 views
0

私は、関数の 'printLine'を書いています - intのリストを与えられて - 水平線を含む文字列を返します。この行の長さは、intのリストの最大値でなければなりません。たとえば:Haskell水平線を印刷

printLine [1, 3, 4, 0] 

は返す必要があります:

+----+----+----+----+ 

を( '+'、長さはハイフンの量によって決定されていることではないに注意してください - 兆候常に5 '+' があるはず - 。看板)

私は、次のコードを書いている:。コードが正しく動作している

printLine :: [Int] -> String 
printLine widthList = concat $ concat $ foldr (:) [["+"]] boundList 
where boundList = replicate 4 ("+" : hyphenList) 
     hyphenList = replicate max "-" 
     max = maximum widthList 

、しかし、私はのように感じます私はこの機能を複雑にしました。たとえば、関数内で 'concat'を2回使用しました。この問題について「クリーン」な方法がありますか?

答えて

3

パートが発生する可能性があります。まもなくこの関数を正確に再利用することはほとんどありません。さらに、数字4と場合によっては文字「+」と「 - 」も「魔法の数字」です。

ための最初のステップは、あなたが機能を再利用することはありません場合でも、より多くの再利用可能な1

-- | renamed from "printLine" because "print" has a connotation of I/O in Haskell 
separator :: Int -> String 
separator = repeatedLine 4 

repeatedLine :: Int -> Int -> String 
repeatedLine reps segmentWidth = ... 

に機能をオンにすることができ、数4は今、その目的を識別する名前(reps)を持っています。

コア機能をオンにします。折りたたみはreverse["+"]:です。 boundListが最初に'+'を付加するので、逆転が必要です。最適な最適化ですが、組み合わせが複雑になります。しかし、あなたはそれを行う、あなたはこれらのすべての詳細を処理するようだ。しかし、代替の視点があります:無限遠から始めましょう。既に持っているので

where segment = '+':replicate segmentWidth '-' 

これを繰り返す必要があります。これを行う最も簡単な方法は、cycle segmentで、セグメントの無限リストを生成します。正しい接頭辞を取るだけで済むので、すべての複雑さが数学的なビットに変わります。

repeatedLine :: Int -> Int -> String 
repeatedLine reps segmentWidth = take (1+reps*(segmentWidth+1)) $ cycle segment 
    where segment = '+':replicate segmentWidth '-' 

ボーナス:最小限の反復回数になりました。

0

いくつかの発言:hyphenList = replicate max "-"

  • "-"はそうhyphenListは、文字列のリストになります文字列です。代わりに'-'を使用した方が簡単です。これによりhyphenListが文字列になり、concatのうちの1つを取り除くのに役立ちます。
  • maxという名前の関数が既にあるので、変数maxの名前を変更したいと思います。maxPreludeに定義されています。
  • の機能をData.Listから使用すると、折りたたみと他の連結を簡素化できます。
  • intercalateは、生成された文字列の最初と最後にセパレータを追加しないため、手動で追加する必要があります。

だから、あなたが得るすべて一緒にそれを置く:関数が一度にあまりにも多くを行うにしようとしているので、合併症の

printLine :: [Int] -> String 
printLine widthList = "+" ++ intercalate "+" boundList ++ "+" 
    where boundList = replicate 4 hyphenList 
     hyphenList = replicate m '-' 
     m = maximum widthList 
+1

あなたが最初と最後にプラス記号が欠落している - あなたは 'のように、他の方法でラウンドを挿入なかった場合は、それらを取得したいですintercalate(レプリケート4 ' - ')(レプリケート5 "+") ' –

+0

@DavidFletcherそれは良い考えです。私はできるだけOPに近づくように問題を別に修正しました。 – redneb

1

@デビッドフレッチャーさんのコメントは素晴らしい解決策につながる:

printLine :: [Int] -> String 
printLine xs = intercalate (replicate (maximum xs) '-') (replicate 5 "+")