Split a given rectangle into n guides

Preliminary notes

I study Haskell.

A question , which I answered a few days ago, gave me inspiration for this exercise in Haskell, which made it possible to experiment with several things, still found out, and also left me questions :)

Problem Statement

For a rectangle A of width wand height, hfind the best rectangle B that matches ntimes within A , where best means the smallest perimeter.

My attempt

I started with the basic idea of ​​creating a set of sub-rectangles A having an area equal to div (w * h) n, and then choosing the one that has the smallest perimeter.

Here are three implementations of this idea that I came up with; they are in chronological order: I got inspiration for the third after I made the second, which I got after I made the first (OK, there is version 0 in which I did not use data Rectangle, but just a tuple (x, y)):

Implementation 1

data Rectangle = Rectangle { width :: Integer,
                             height :: Integer
                           } deriving (Show)

subRectangles :: Rectangle -> Integer -> [ Rectangle ]
subRectangles r n = [ Rectangle x y | x <- [1..w ], y <- [1..h], x * y == (w * h) `div` n ]
                  where w = width r
                        h = height r

bestSubRectangle :: [ Rectangle ] -> Rectangle
bestSubRectangle [ r ] = r
bestSubRectangle (r:rs)
  | perimeter r < perimeter bestOfRest = r
  | otherwise = bestOfRest
  where bestOfRest = bestSubRectangle rs

perimeter :: Rectangle -> Integer
perimeter r = (width r) + (height r)

Implementation 2

data Rectangle = Rectangle { width :: Integer,
                             height :: Integer
                           } deriving (Show)

subRectangles :: Rectangle -> Integer -> [ Rectangle ]
subRectangles r n = [ Rectangle x y | x <- [1..w ], y <- [1..h], x * y == (w * h) `div` n ]
                  where w = width r
                        h = height r

bestSubRectangle :: [ Rectangle ] -> Rectangle
bestSubRectangle xs = foldr smaller (last xs) xs

smaller :: Rectangle -> Rectangle -> Rectangle
smaller r1 r2 
  | perimeter r1 < perimeter r2 = r1
  | otherwise = r2

perimeter :: Rectangle -> Integer
perimeter r = (width r) + (height r)

Implementation 3

import Data.List

data Rectangle = Rectangle { width :: Integer,
                             height :: Integer
                           } deriving (Show, Eq)

instance Ord Rectangle where
  (Rectangle w1 h1) `compare` (Rectangle w2 h2) = (w1 + h1) `compare` (w2 + h2)

subRectangles :: Rectangle -> Integer -> [ Rectangle ]
subRectangles r n = [ Rectangle x y | x <- [1..w ], y <- [1..h], x * y == (w * h) `div` n ]
                  where w = width r
                        h = height r

bestSubRectangle :: [ Rectangle ] -> Rectangle
bestSubRectangle = head . sort

Questions

  • Which approach is more idiomatic?

  • ? bestSubRectangle 3 sort, O (n lg n), 1, 2 bestSubRectangle , subRectangles, O (n), , , lack- Haskell bestSubRectangle = head . sort: sort , head (head (x:_) = x)?

  • 3 Rectangle Ord Ord? Rectangle Ord?

/ .

+5
2

Haskell ( ):

  • , .
  • , , sort , . , , - head . sort sort. , , sort, , . , .
  • Ord , compare . - : compare, <=. . , .

( , ):

  • , , - Haskell . , perimeter r = width r + height r
  • , , foldr1, bestSubRectangle xs = foldr1 smaller xs
  • Ord Rectangle Eq. , compare Eq, False ==. Rectangle Ord smaller, .
+4

, , n ( , ), :

  • n = 1 = >
  • n = 2 = > 2 , ,
  • n = 3 = > , 2, 3, .
  • n = 4 , , : 4 , 2x2. n > 1

- , n, THEN, , (.. ) MOST SIMILAR, ( ). , . .

  • n =
  • l =
  • s =
  • h1 = 1
  • w1 = - 1
  • d =
  • t = ( t l)
  • b =

:

    1: Factor n
    2: for each factor pair of n:
       (l/largest factor) - (s/smaller factor) = d
       if d < t:
          t = d
          store current best candidate rectangle 
    3: Return best fit remaining after all factors have been tried
+1

All Articles