2014-10-01 8 views
7

Do zadania muszę napisać jakiś kod Haskella, który ma jako dane wejściowe skończoną listę składającą się z nieskończonej listy liczb całkowitych, każda lista monotonicznie rośnie.Jak mogę połączyć skończoną liczbę nieskończonych list w Haskell?

Teraz muszę połączyć je w jedną listę, która zamawia liczby całkowite. Ponadto wiele liczb całkowitych może pojawić się na wielu listach: na liście wyników każda liczba całkowita może pojawić się tylko raz na liście.

Więc jeśli dane wejściowe to na przykład [[1, 2, 6, 10, 28, 40, ...] [3, 4, 10, 28, 100, ...], [dowolna liczba list ]] wtedy wynik powinien wynosić [1, 2, 3, 4, 6, 10, 28, 40, 100, ...]

Trochę utknąłem tutaj. Nie wiem, jak skutecznie używać foldr do łączenia list. Myślę, że powinienem porównać szefów każdej listy i sporządzić z niej nową listę.

+0

Sortowanie nieskończonych list nie jest zazwyczaj łatwe. Gdybym miał dane wejściowe '[[1, 3, 4, 5, 6, ...], [1, 3, 5, 7, ..]]', i zacznę je sortować, aby uzyskać '[1, 3 , 4, 5, 6, 7, ...] ', skąd mam wiedzieć, że 2 nie pojawia się gdzieś na tych dwóch listach wejściowych? – bheklilr

+6

Nie jest to możliwe, chyba że wiesz, że listy są monotonicznie rosnące, co, jak zgaduję, jest podane w przypisaniu. Czy możesz potwierdzić i pokazać nam, co wypróbowałeś? Ludzie tutaj są zwykle bardziej pomocni, jeśli robisz więcej niż mówisz "pokaż mi jak". –

+0

Podejrzewam z przykładowych danych, że każda lista wejściowa jest już posortowana, a scalenie jest wszystkim, co jest wymagane. – AndrewC

Odpowiedz

7

Możesz nieco uprościć problem, myśląc o połączeniu dwóch nieskończonych list posortowanych, a następnie spróbuj uogólnić. Szkielet tej seryjnej będzie wyglądać następująco:

mergeSorted :: Ord a => [a] -> [a] -> [a] 
mergeSorted [] ys = ys 
mergeSorted xs [] = xs 
mergeSorted (x:xs) (y:ys) = ??? 

Musisz porównać x i y, a zrobić coś sensownego, prawdopodobnie z udziałem rekurencyjne wywołanie mergeSorted: To nie wygląda tak źle, prawda ?

Teraz wyobraźmy sobie, że mergeSorted działa i możesz zamienić dwie nieskończone posortowane listy w jedną nieskończoną posortowaną listę. Jak zmienić N nieskończonych posortowanych list w jedną posortowaną listę? Dlaczego, to prosty krotnie! Po prostu połącz dwie listy razem, a następnie połącz trzecią z tą i czwartą z tą i tak dalej.

mergeAll :: Ord a => [[a]] -> [a] 
mergeAll xss = foldr ??? 
+0

Ugryzie, nie widzę, jak rozwiążesz fałsz scalania dla '[[1], [7], [3], [2]]' – mhitza

+0

@mhitza (** uwaga do OP * *, możesz uznać to za ** spoiler **): łatwy. 'mergeAll = foldr mergeSorted []; mergeAll [[1], [7], [3], [2]] "następnie ocenia jako" [1,2,3,7] "zgodnie z oczekiwaniami. – amalloy

+0

wow, czuję się jak idiota, wyobrażałem sobie coś innego :) – mhitza

1

Możemy połączyć każdą parę nieskończonych monotonicznie rosnącą list (takich jak masz) przez wielokrotne pociągnięcie minimalny elementu z jednej z list, przez unfoldr pull (unfoldr jest w Data.List), z

pull (x:xs,y:ys) | x<y = Just (x, (xs,y:ys)) 
       | x>y = Just (y, (x:xs,ys)) 
       | x==y = Just (x, (xs, ys)) -- pull same from both (NB!) 

i możemy przetworzyć każdą skończoną listę według parach, połowę jej długości:

pairs f (x:y:t) = f (x,y) : pairs f t 
pairs _ t  = t 

Aby powtórzyć krok, dopóki warunek jest spełniony, to praca until:

uniquelyMerge xs = ... (until (...) (pairs (unfoldr pull)) xs) 
..... 

Nie zapomnij obsłużyć pusta lista sprawę.

Powiązane problemy