No pude resistirme. Aquí está el código de mi puerto de Rafe para Haskell:
module Langford where
import Control.Applicative
import Control.Monad
import Data.Array
import Data.List
import Data.Ord
import Data.Tuple
import qualified Data.IntSet as S
langford :: Int -> [[Int]]
langford n
| mod n 4 `elem` [0, 3] = map (pairingToList n) . search $ initial n
| otherwise = []
type Variable = (Int, S.IntSet)
type Assignment = (Int, Int)
type Pairing = [Assignment]
initial :: Int -> [Variable]
initial n = [(i, S.fromList [1..(2*n-i-1)]) | i <- [1..n]]
search :: [Variable] -> [Pairing]
search [] = return []
search vs = do
let (v, vs') = choose vs
a <- assignments v
case prune a vs' of
Just vs'' -> (a :) <$> search vs''
Nothing -> mzero
choose :: [Variable] -> (Variable, [Variable])
choose vs = (v, filter (\(j, _) -> i /= j) vs)
where [email protected](i, _) = minimumBy (comparing (S.size . snd)) vs
assignments :: Variable -> [Assignment]
assignments (i, d) = [(i, k) | k <- S.toList d]
prune :: Assignment -> [Variable] -> Maybe [Variable]
prune a = mapM (prune' a)
prune' :: Assignment -> Variable -> Maybe Variable
prune' (i, k) (j, d)
| S.null d' = Nothing
| otherwise = Just (j, d')
where d' = S.filter (`notElem` [k, k+i+1, k-j-1, k+i-j]) d
pairingToList :: Int -> Pairing -> [Int]
pairingToList n = elems . array (1, 2*n) . concatMap positions
where positions (i, k) = [(k, i), (k+i+1, i)]
Parece que funciona bastante bien.Estas son algunas de temporizaciones de GHCi:
Prelude Langford> :set +s
Prelude Langford> head $ langford 4
[4,1,3,1,2,4,3,2]
(0.03 secs, 6857080 bytes)
Prelude Langford> head $ langford 32
[32,28,31,23,26,29,22,24,27,15,17,11,25,10,30,5,20,2,21,19,2,5,18,11,10, ...]
(0.05 secs, 15795632 bytes)
Prelude Langford> head $ langford 100
[100,96,99,91,94,97,90,92,95,83,85,82,93,78,76,73,88,70,89,87,69,64,86, ...]
(0.57 secs, 626084984 bytes)
El algoritmo debe ser relativamente independiente de la lengua en uso. (Y además, si esto es más que un ejercicio educativo, que está además probablemente mejor simplemente usando soluciones calculadas fácilmente-) – delnan
según la Wikipedia, se trata de un problema de cobertura exacta, que son NP completa en general. No estoy seguro si ese resultado se aplica a este problema en particular. – luqui
He aquí un programa en Perl que es posible que desee estudiar: http://legacy.lclark.edu/~miller/langford/ROD.pl –