Comparing High-dimensional Objects
Lots of researchers have studied children’s perceptions of the size of multidimensional objects. Children compare two lines with reasonable accuracy, but how about comparing two rectangles of differing aspect ratios? Or two containers of liquid, one short and squat, the other tall and narrow?
Based on a some experiments I read in Duckworth’s The Having of Wonderful Ideas, I decided to try out an activity on two of my own children. Each receives the same number of cubic blocks. Each is to independently build a rectangular prism out of those blocks, with no knowledge of the other’s choice of dimensions. Then we compare the two structures.
While they are building, I secretly hope they build structures of different dimensions. To increase the chances of this, I need to provide a number of blocks that can be decomposed into three factors—height, width, and depth—in many different ways. For example, 8 blocks can be composed into prisms of three possible configurations: 8x1x1, 4x2x1, and 2x2x2. I had guesses about which numbers would be good choices, but I thought proving their goodness with a program might help me strengthen my Haskell muscle a bit.
First I made some data types to help me model the problem. Triplet
represents the three dimensions of a prism, while VolumeAndTriplets
is the pair of a volume and its list of possible dimensions that multiply up to that volume. I implemented compare
to help me select our the volumes with the most number of possible triplets, favoring smaller volumes over larger ones in the case of a tie:
type Triplet = (Int, Int, Int) data VolumeAndTriplets = VolumeAndTriplets Int [Triplet] deriving (Eq) instance Ord VolumeAndTriplets where (VolumeAndTriplets volume1 triplets1) `compare` (VolumeAndTriplets volume2 triplets2) = if ntriplets1 == ntriplets2 then volume1 `compare` volume2 else ntriplets2 `compare` ntriplets1 where ntriplets1 = length triplets1 ntriplets2 = length triplets2 instance Show VolumeAndTriplets where show (VolumeAndTriplets n triplets) = show n ++ " has " ++ show (length triplets) ++ " triplets: " ++ show triplets
From there, I wrote factorVolume
to compute the list of possible dimensions for a single volume. List comprehensions were a good fit for this task:
-- Compute list of all triplets that multiply to a given volume. factorVolume :: Int -> [Triplet] factorVolume volume = [(a, b, c) | a <- [1..volume], b <- [1..a], c <- [1..b], a * b * c == volume]
Running factorVolume 24
produces the following list:
[(4,3,2),(6,2,2),(6,4,1),(8,3,1),(12,2,1),(24,1,1)]
Since I wanted to choose among many volumes, I wrote factorVolumes
to map over a list of possible volumes and produce a list of volumes and their triplet lists:
-- Compute all possible triplet lists up to a given volume. factorVolumes :: Int -> [VolumeAndTriplets] factorVolumes upper = map (\volume -> VolumeAndTriplets volume (factorVolume volume)) [1..upper]
Running factorVolumes 10
produces the following output:
1 has 1 triplets: [(1,1,1)] 2 has 1 triplets: [(2,1,1)] 3 has 1 triplets: [(3,1,1)] 4 has 2 triplets: [(2,2,1),(4,1,1)] 5 has 1 triplets: [(5,1,1)] 6 has 2 triplets: [(3,2,1),(6,1,1)] 7 has 1 triplets: [(7,1,1)] 8 has 3 triplets: [(2,2,2),(4,2,1),(8,1,1)] 9 has 2 triplets: [(3,3,1),(9,1,1)] 10 has 2 triplets: [(5,2,1),(10,1,1)]
Now I wanted to find the volumes up through 64 with the most factors:
main = (putStr . unlines . map show . take 10 . sort) $ factorVolumes 64
This gave me the following output:
60 has 10 triplets: [(5,4,3),(6,5,2),(10,3,2),(10,6,1),(12,5,1),(15,2,2),(15,4,1),(20,3,1),(30,2,1),(60,1,1)] 48 has 9 triplets: [(4,4,3),(6,4,2),(8,3,2),(8,6,1),(12,2,2),(12,4,1),(16,3,1),(24,2,1),(48,1,1)] 36 has 8 triplets: [(4,3,3),(6,3,2),(6,6,1),(9,2,2),(9,4,1),(12,3,1),(18,2,1),(36,1,1)] 64 has 7 triplets: [(4,4,4),(8,4,2),(8,8,1),(16,2,2),(16,4,1),(32,2,1),(64,1,1)] 24 has 6 triplets: [(4,3,2),(6,2,2),(6,4,1),(8,3,1),(12,2,1),(24,1,1)] 40 has 6 triplets: [(5,4,2),(8,5,1),(10,2,2),(10,4,1),(20,2,1),(40,1,1)] 54 has 6 triplets: [(6,3,3),(9,3,2),(9,6,1),(18,3,1),(27,2,1),(54,1,1)] 56 has 6 triplets: [(7,4,2),(8,7,1),(14,2,2),(14,4,1),(28,2,1),(56,1,1)] 30 has 5 triplets: [(5,3,2),(6,5,1),(10,3,1),(15,2,1),(30,1,1)] 32 has 5 triplets: [(4,4,2),(8,2,2),(8,4,1),(16,2,1),(32,1,1)]
Despite this program telling me that 60 blocks would be the volume most likely to produce prisms of differing dimensions, we don't own a set of blocks large enough. Instead, I gave each son 24 blocks. They went to separate locations in the house. My 7-year-old built a 6x2x2 structure quickly, and my 5-year-old went through several attempts. At first, he didn't use all the blocks. His next structure wasn't a rectangular prism—all the blocks were in disarray. I told him they needed to be tightly packed to look like a box, and his third attempt was a 6x4x1 prism.
Then I sent one boy away and asked the remaining to compare the two structures. Was the 5-year-old's structure bigger than, smaller than, or the same size as the 7-year-old's? My 5-year-old said his was bigger. My 7-year-old said the 5-year-old's was bigger, qualifying "bigger" as "wider." Thus, they were in agreement.
At this point, I got out a couple of vases while they weren't looking. One was short and squat and the other tall and narrow. I filled each with 2 cups of water. Showing them to my sons, I asked, "Suppose you were really, really thirsty. Which of these would you rather drink out of?" My 5-year-old said the short and squat one because it held more. With both the prisms and the vases, to him width and depth were the most salient dimensions. If the width and depth were more, the difference in height was disregarded. My 7-year-old guessed that they contained the amount, seeing that the narrow width of the second vase squeezed the water upward. My 5-year-old didn't agree.
We emptied the short and squat vase. We placed a rubber band around the tall narrow one marking the level of the water, and then poured its contents in the short and squat one. The water reached a much lower height than the rubber band. I asked my 5-year-old, "Is that the same amount of water that was just in the tall vase?" He said yes. I asked, "How high would the water be if I poured it out on the kitchen floor?" He said, "Not even an inch."
Then we revisited the prisms made out of blocks. I asked, "What do you think about the sizes now?" My 7-year-old said that they were the same. "How do you know that?" I asked. He counted the blocks and found 24 in each.
We closed the experiment by talking about how we can't always trust our eyes when it comes to comparing objects of many dimensions. My 7-year-old suggested that we can be more accurate by counting.