De Bruijn sequences: Difference between revisions

Content added Content deleted
(Added 11l)
(→‎{{header|Haskell}}: added solution)
Line 1,319: Line 1,319:
PIN number 5814 is missing
PIN number 5814 is missing
PIN number 8145 is missing</pre>
PIN number 8145 is missing</pre>

=={{header|Haskell}}==

Straight-forward implementation of inverse Burrows—Wheeler transform [https://en.wikipedia.org/wiki/De_Bruijn_sequence#Construction] is reasonably efficient for the task (about a milliseconds for B(10,4) in GHCi).

<lang haskell>import Data.List
import Data.Map ((!))
import qualified Data.Map as M

-- represents a permutation in a cycle notation
cycleForm :: [Int] -> [[Int]]
cycleForm p = unfoldr getCycle $ M.fromList $ zip [0..] p
where
getCycle p
| M.null p = Nothing
| otherwise =
let Just ((x,y), m) = M.minViewWithKey p
c = if x == y then [] else takeWhile (/= x) (iterate (m !) y)
in Just (c ++ [x], foldr M.delete m c)

-- the set of Lyndon words generated by inverse Burrows—Wheeler transform
lyndonWords :: Ord a => Int -> [a] -> [[a]]
lyndonWords k s = map (ref !!) <$> cycleForm perm
where
ref = concat $ replicate (length s ^ (k - 1)) s
perm = s >>= (`elemIndices` ref)

-- returns the de Bruijn sequence of order k for an alphabeth s
deBruijn :: Ord a => Int -> [a] -> [a]
deBruijn k s = let lw = concat $ lyndonWords k s
in lw ++ take (k-1) lw</lang>

<pre>λ> cycleForm [1,4,3,2,0]
[[1,4,0],[3,2]]

λ> lyndonWords 3 "ab"
["a","aab","abb","b"]

λ> deBruijn 3 "ab"
"aaababbbaa"</pre>

The task.

<lang haskell>import Control.Monad (replicateM)

main = do
let symbols = ['0'..'9']
let db = deBruijn 4 symbols
putStrLn $ "The length of de Bruijn sequence: " ++ show (length db)
putStrLn $ "The first 130 symbols are:\n" ++ show (take 130 db)
putStrLn $ "The last 130 symbols are:\n" ++ show (drop (length db - 130) db)

let words = replicateM 4 symbols
let validate db = filter (not . (`isInfixOf` db)) words
putStrLn $ "Words not in the sequence: " ++ unwords (validate db)

let db' = a ++ ('.': tail b) where (a,b) = splitAt 4444 db
putStrLn $ "Words not in the corrupted sequence: " ++ unwords (validate db') </lang>

<pre>λ> main
The length of de Bruijn sequence: 10003
The first 130 symbols are:
"0000100020003000400050006000700080009001100120013001400150016001700180019002100220023002400250026002700280029003100320033003400350"
The last 130 symbols are:
"6898689969697769786979698769886989699769986999777787779778877897798779978787978887889789878997979887989799879998888988998989999000"
Words not in the sequence:
Words not in the corrupted sequence: 1459 4591 5914 8145</pre>


=={{header|J}}==
=={{header|J}}==