How to resolve the algorithm Water collected between towers step by step in the Haskell programming language

Published on 7 June 2024 03:52 AM

How to resolve the algorithm Water collected between towers step by step in the Haskell programming language

Table of Contents

Problem Statement

In a two-dimensional world, we begin with any bar-chart (or row of close-packed 'towers', each of unit width), and then it rains, completely filling all convex enclosures in the chart with water.

In the example above, a bar chart representing the values [5, 3, 7, 2, 6, 4, 5, 9, 1, 2] has filled, collecting 14 units of water. Write a function, in your language, from a given array of heights, to the number of water units that can be held in this way, by a corresponding bar chart. Calculate the number of water units that could be collected by bar charts representing each of the following seven series:

See, also:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Water collected between towers step by step in the Haskell programming language

Water Collected Between Towers

Both snippets of code solve the same problem: calculating the amount of water collected between a series of towers. Let's break down each implementation:

First Solution:

  • The first solution uses the Data.Vector.Unboxed library to store the tower heights as a vector.
  • It defines a function waterCollected that takes a vector of tower heights as input and calculates the total amount of water collected.
  • It uses a series of higher-order functions to perform the following steps:
    • It scans the vector from left to right and from right to left, finding the maximum height of any tower to the left and right of each position.
    • It calculates the difference between the minimum of the two maximum heights for each position, representing the amount of water that can be collected at that position.
    • It filters out any negative values (indicating no water) and sums the positive values to get the total water collected.
  • In main, it creates several lists of tower heights and calculates the water collected for each using the waterCollected function. It then prints the results.

Second Solution:

  • The second solution uses the Data.List library to store the tower heights as a list.
  • It defines a function towerPools that takes a list of tower heights as input and returns a list of pairs. Each pair represents the minimum height between two towers and the amount of water that can be collected between them.
  • It first scans the list from left to right and from right to left, finding the maximum height of any tower to the left and right of each position.
  • It then calculates the minimum height between the two maximum heights for each position and subtracts this value from the maximum height on that side, effectively finding the amount of water that can be collected.
  • In main, it creates several lists of tower heights and calculates the water pools for each using the towerPools function. It then prints the results.

Additional Features in the Second Solution:

  • It includes two additional functions, display and showTowers, which are used to create a diagram of the towers and the water collected between them.
  • This provides a visual representation of the water collection, making it easier to understand the results.

Overall, both solutions effectively calculate the amount of water collected between towers, with the second solution providing additional visualization features.

Source code in the haskell programming language

import Data.Vector.Unboxed (Vector)
import qualified Data.Vector.Unboxed as V

waterCollected :: Vector Int -> Int
waterCollected =
  V.sum .            -- Sum of the water depths over each of
  V.filter (> 0) .   -- the columns that are covered by some water.
  (V.zipWith (-) =<< -- Where coverages are differences between:
   (V.zipWith min .  -- the lower water level in each case of:
    V.scanl1 max <*> -- highest wall to left, and
    V.scanr1 max))   -- highest wall to right.

main :: IO ()
main =
  mapM_
    (print . waterCollected . V.fromList)
    [ [1, 5, 3, 7, 2]
    , [5, 3, 7, 2, 6, 4, 5, 9, 1, 2]
    , [2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1]
    , [5, 5, 5, 5]
    , [5, 6, 7, 8]
    , [8, 7, 7, 6]
    , [6, 7, 10, 7, 6]
    ]


import Data.List (replicate, transpose)

-------------- WATER COLLECTED BETWEEN TOWERS ------------

towerPools :: [Int] -> [(Int, Int)]
towerPools =
  zipWith min . scanl1 max <*> scanr1 max
    >>= zipWith ((<*>) (,) . (-))


--------------------------- TEST -------------------------
main :: IO ()
main =
  mapM_
    (putStrLn . display . towerPools)
    [ [1, 5, 3, 7, 2],
      [5, 3, 7, 2, 6, 4, 5, 9, 1, 2],
      [2, 6, 3, 5, 2, 8, 1, 4, 2, 2, 5, 3, 5, 7, 4, 1],
      [5, 5, 5, 5],
      [5, 6, 7, 8],
      [8, 7, 7, 6],
      [6, 7, 10, 7, 6]
    ]

------------------------- DIAGRAMS -----------------------

display :: [(Int, Int)] -> String
display = (<>) . showTowers <*> (('\n' :) . showLegend)

showTowers :: [(Int, Int)] -> String
showTowers xs =
  let upper = maximum (fst <$> xs)
   in '\n' :
      ( unlines
          . transpose
          . fmap
            ( \(x, d) ->
                concat $
                  replicate (upper - (x + d)) " "
                    <> replicate d "x"
                    <> replicate x "█"
            )
      )
        xs

showLegend :: [(Int, Int)] -> String
showLegend =
  ((<>) . show . fmap fst)
    <*> ((" -> " <>) . show . foldr ((+) . snd) 0)


  

You may also check:How to resolve the algorithm Anagrams step by step in the Elena programming language
You may also check:How to resolve the algorithm Brilliant numbers step by step in the Mathematica/Wolfram Language programming language
You may also check:How to resolve the algorithm Maze generation step by step in the EDSAC order code programming language
You may also check:How to resolve the algorithm Compiler/code generator step by step in the Phix programming language
You may also check:How to resolve the algorithm Rosetta Code/Rank languages by popularity step by step in the Tcl programming language