Как напечатать несколько треугольников в одной строке (ХАСКЕЛЛ)

#haskell #recursion #triangle

Вопрос:

У меня есть это определение IO() Triangle , в котором каждая строка треугольника является элементом в списке:

 import Data.List ( intersperse )
type Triangle = Char -> Int -> [String]

centeredTriangle :: Triangle
centeredTriangle c n = [replicate (n-i) ' '    intersperse ' ' (replicate i c) | i <- [0 .. n]]
 

Выход:

 Ok, one module loaded.
ghci> centeredTriangle '*' 6
["      ","     *","    * *","   * * *","  * * * *"," * * * * *","* * * * * *"]
 

Когда я запускаю свою основную функцию, я печатаю unlines треугольник следующим образом:

 triangles :: Int -> Int -> Int -> IO()
triangles a b c = do 
    putStr $ unlines $ centeredTriangle '*' a
    putStr $ unlines $ centeredTriangle '*' b 
    putStr $ unlines $ centeredTriangle '*' c
 

Выход:

 ghci> triangles 1 2 3

*

 *
* *

  *
 * *
* * *
 

Я хочу напечатать треугольники на одной линии, вот так:

 ghci> triangles 1 2 3

               *
       *      * *
 *    * *    * * *
 

Я понимаю, что это может оказаться более сложной задачей, чем я ожидал, но моей первой мыслью было использовать centeredTriangle нижнюю строку (последний элемент списка) каждого треугольника и объединить их в новую строку, которую я затем помещу в качестве последнего элемента в новый список строк. Я подумал, что если я сделаю это для каждого элемента (начиная с последнего) и до самого верха, я смогу напечатать треугольники в одной строке, используя мою основную функцию. Как мне этого добиться?

Комментарии:

1. Что именно вы подразумеваете под «на одной линии»? Можете ли вы добавить точный вывод, который вы хотите, в свой вопрос?

2. Вам нужно будет добавить нужное количество вертикального и горизонтального пространства, чтобы это сработало. Возможно, вы могли бы начать с создания функции для добавления заданного количества отступов в a [String] , предполагая, что она «прямоугольная». Затем поместите треугольники так, чтобы они имели одинаковый размер X*Y. Наконец, соединим их горизонтально.

3. Представьте, что мы изменим centeredTriangle так, чтобы каждая линия была фактически полной длиной «основания»треугольника. Таким образом, вторая строка для 3-треугольника будет » * «вместо» *». Это облегчило бы написание функции, которая помещала бы две из этих фигур (все еще рассматриваемых как списки строк) рядом друг с другом. Вы бы позвонили только unlines в самом конце, после того, как сложите все цифры вместе.

Ответ №1:

С помощью type Triangle = [String] ,

  1. Напишите функцию boundingBox :: Triangle -> (Int,Int) .
  2. Напишите функцию maxBoundingBox :: [Triangle] -> (Int,Int) .
  3. Напишите функцию putInBox :: Triangle -> (Int,Int) -> Triangle .
  4. Напишите функцию makeSameSize :: [Triangle] -> [Triangle] .
  5. Напишите функцию sideToSide :: Triangle -> [String] -> [String] .

Используйте его, foldr чтобы объединить все размеры Triangle s вместе.

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