2012-01-06 18 views
10

Dla tych, którzy mają podejrzane umysły, to nie jest praca domowa, tylko ciekawa.Nieskończona lista nieskończonych liczników

Biorąc pod uwagę skończony alfabet, czy możliwe jest skonstruowanie listy nieskończenie długich słów wykonanych z alfabetu w odwrotnej kolejności leksykograficznej?

to podano alfabetu "ab"

możliwe jest skonstruowanie listy:

["aaaaaa...", "baaaaa...", "abaaaa...", "bbaaaa...", "aabaaa...", ...] 

gdzie ... przedstawia listę (i listę listy) rozciągający się w nieskończonej długości.

naiwna próba jest:

counters alphabet = [c:ounter | ounter <- counters alphabet, c <- alphabet] 

ale to nie działa, ponieważ pozostało rekurencyjne.

Oczywiście, w wersji roboczej, jeśli próbowałeś wydrukować wynik, zobaczyłbyś tylko pierwszy element drukowany jako nieskończona lista pierwszego elementu z alfabetu. Jednakże, powinieneś być w stanie to zrobić:

mapM_ (print . take 2) . take 4 . counters $ "ab" 

i zobaczyć wyjście:

aa 
ba 
ab 
bb 
+3

jesteście świadomi są uncountably wiele słów, więc lista nie będzie zawierać wszystkie z nich? – sdcvvc

+0

nie ma izomorfizmu do zbioru liczb całkowitych dodatnich? A na prawo od ostatniego b są jak wiodące zera w liczbie całkowitej – pat

+2

Tak, ale pisałeś w pytaniu "wszystkie nieskończenie długie słowa"; to nie wszystko, tylko te, które składają się z "a" z pewnego punktu. – sdcvvc

Odpowiedz

11

Dlaczego nie fix to?

ghci> let bar = let foo ~(st:sts) = [c:st | c <- "ab"] ++ foo sts in fix foo 
ghci> take 5 . map (take 5) $ bar 
["aaaaa","baaaa","abaaa","bbaaa","aabaa"] 
take 10 . map (take 5) $ bar 
["aaaaa","baaaa","abaaa","bbaaa","aabaa","babaa","abbaa","bbbaa","aaaba","baaba"] 
+0

Słodki! Uświadomiłem sobie, że potrzebny jest leniwy wzór, ponieważ nie można rozstrzygnąć, czy wynik nie był pusty. – pat

7

Prawdopodobnie nie jest to najbardziej efektywne rozwiązanie, ale przynajmniej to działa:

counters alphabet = map f [0..] 
    where f n = let (q, r) = quotRem n (length alphabet) in alphabet !! r : f q 
> take 10 $ map (take 5) $ counters "ab" 
["aaaaa","baaaa","abaaa","bbaaa","aabaa","babaa","abbaa","bbbaa","aaaba","baaba"] 
1

Progresja wygląda jak kodowanie numeru bazowego N z najmniej znaczącym wykopem to po lewej stronie, więc możemy zbliżyć go jako

  1. Zrób „N” do bazy przy użyciu funkcji falfabetów jak litery.
  2. mapf do [0..]
  3. Append repeat $ head alphabets do każdego elementu listy.
6

można znaleźć następujące podejście zabawny/mylące:

duplicates s ss = cycle ss : duplicates s (ss >>= \c -> s >> [c]) 
counters = transpose . join duplicates 

ten pochodzi z obserwacji, że pierwsze litery naśladowania wzór "ababab...", drugi litery naśladowania wzór "aabbaabbaabb..." litery trzecie naśladowania wzór "aaaabbbbaaaabbbb...", itp.

+0

Bardzo ładne. +1 na pewno. –

2

Co z tym?

[email protected](a:as) = a:('b':a):concatMap (\x -> ['a':x,'b':x]) as where a = ['a','a'..] 

także (\x -> ['a':x,'b':x]) mogą być napisane w Applicative jak ([('a':),('b':)] <*>) . pure jeśli wziąć pod uwagę, że jest to bardziej eleganckie.

1

Jeszcze inna wersja opiera się na idei Daniela:

counters = transpose $ map cycle $ iterate (>>= \x -> [x,x]) "ab" 
+0

Uwielbiam prostotę! Świetny sposób na generowanie słów z dowolnego alfabetu! Dla każdego, kto się zastanawia, '(>> = \ x -> [x, x])' równa się 'concat. map (\ x -> [x, x]) 'dla list. Dlatego też złożoność jest optymalna. –

Powiązane problemy