import Data.List (genericLength, sort, permutations)
import Data.Matrix
-- 1ª definición de torres
-- =======================
torres1 :: Int -> [Matrix Int]
torres1 n =
[permutacionAmatriz n p | p <- sort (permutations [1..n])]
permutacionAmatriz :: Int -> [Int] -> Matrix Int
permutacionAmatriz n p =
matrix n n f
where f (i,j) | (i,j) `elem` posiciones = 1
| otherwise = 0
posiciones = zip [1..n] p
-- 2ª definición de torres
-- =======================
torres2 :: Int -> [Matrix Int]
torres2 = map fromLists . permutations . toLists . identity
-- El cálculo con la definición anterior es:
-- λ> identity 3
-- ( 1 0 0 )
-- ( 0 1 0 )
-- ( 0 0 1 )
--
-- λ> toLists it
-- [[1,0,0],[0,1,0],[0,0,1]]
-- λ> permutations it
-- [[[1,0,0],[0,1,0],[0,0,1]],
-- [[0,1,0],[1,0,0],[0,0,1]],
-- [[0,0,1],[0,1,0],[1,0,0]],
-- [[0,1,0],[0,0,1],[1,0,0]],
-- [[0,0,1],[1,0,0],[0,1,0]],
-- [[1,0,0],[0,0,1],[0,1,0]]]
-- λ> map fromLists it
-- [( 1 0 0 )
-- ( 0 1 0 )
-- ( 0 0 1 )
-- ,( 0 1 0 )
-- ( 1 0 0 )
-- ( 0 0 1 )
-- ,( 0 0 1 )
-- ( 0 1 0 )
-- ( 1 0 0 )
-- ,( 0 1 0 )
-- ( 0 0 1 )
-- ( 1 0 0 )
-- ,( 0 0 1 )
-- ( 1 0 0 )
-- ( 0 1 0 )
-- ,( 1 0 0 )
-- ( 0 0 1 )
-- ( 0 1 0 )
-- ]
-- 1ª definición de nTorres
-- ========================
nTorres1 :: Int -> Integer
nTorres1 = genericLength . torres1
-- 2ª definición de nTorres
-- ========================
nTorres2 :: Int -> Integer
nTorres2 n = product [1..fromIntegral n]
-- Comparación de eficiencia
-- =========================
-- λ> nTorres1 9
-- 362880
-- (4.22 secs, 693,596,128 bytes)
-- λ> nTorres2 9
-- 362880
-- (0.00 secs, 0 bytes)