Wydaje się, że wolą naprawić swój kod niż zacząć od nowa, tak rzućmy okiem na kodzie.Po pierwsze, głównym lista krojenia:
reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs))
Teraz reverse (take i (reverse xs))
trwa i
elementów z końca listy, ale odwrócić listę dwa razy, aby osiągnąć ten cel, a byłoby lepiej zrobić drop (length xs - i) xs
. Podobnie można wdrożyć reverse (drop i (reverse xs)))
jako take (length xs - i) xs
. To daje nam
drop (length xs - i) xs ++ take (length xs - i) xs
Teraz kod \i->[1..n]<=n
nie ma sensu, ponieważ porównuje listę [1..n]
z n
, który nie może pracować. Myślę, że próbujesz utworzyć pętlę, w której i
działa od 1
do n
, co jest dobrym planem. Użyjmy wyrażeń listowych, aby uzyskać te chcieliśmy:
[drop (length xs - i) xs ++ take (length xs - i) xs | i <- [1 .. length xs], i <= n]
ale teraz mamy uruchomiony od 1 do długości listy, ale wyrzucać numery powyżej n
, które byłyby lepiej napisany
[drop (length xs - i) xs ++ take (length xs - i) xs | i <- [1..n]]
To pozwala n
być więcej niż length xs
, ale nie widzę tu dużego problemu, możemy to sprawdzić na początku.
Wskazówka teraz, że mamy tylko używasz i
w postaci (length xs - i)
i naprawdę jesteśmy przeliczania length xs
strasznie dużo więcej niż powinniśmy, więc zamiast pozwolić i
bieg z 1
do n
i używając length xs - i
, Dlaczego po prostu nie mają j=length xs -i
tak j
biegnie od length xs
do length xs - n
:
[drop j xs ++ take j xs | j <- [length xs,length xs - 1 .. length xs - n]]
który działa, ponieważ na przykład [6,5..1] == [6,5,4,3,2,1]
Byłoby neater zrobić
let l = length xs in
[drop j xs ++ take j xs | j <- [l,l - 1 .. l - n]]
a może chcesz take
więcej niż chcesz zrobić arytmetyki, więc możemy użyć:
let l = length xs in
take n [drop j xs ++ take j xs | j <- [l,l - 1 .. 0]]
która ma dodatkową zaletę cię powstrzymuje robisz zbyt wiele, zatrzymujesz się, gdy wrócisz na początek.
Chciałbym zmienić nazwę funkcji z generatingListforRightShifting
do rotationsR
, dając
rotationsR n xs = let l = length xs in
take n [drop j xs ++ take j xs | j <- [l,l - 1 ..]]
Który daje rotationsR 6 [1..4] == [[1,2,3,4],[4,1,2,3],[3,4,1,2],[2,3,4,1],[1,2,3,4]]
.
Lewy obrót będzie wyglądać prościej:
rotationsL n xs = take n [drop j xs ++ take j xs | j <- [0..length xs]]
dygresja: Nie mogłem się powstrzymać, przepraszam, i zacząłem ponownie.
ja nadal nie podoba wszystko, co spada i biorąc za każdym razem, wolałbym pop nieskończenie wiele kopii xs
obok siebie (cycle xs
) i podjąć nieskończenie wiele tails
tego, siekanie je wszystkie odpowiednią długość, ale po prostu podaj pierwsze n:
obrótL 'n xs = niech l = długość xs w weź n. map (weź l). ogony. Cykl xs
Ponieważ oceny leniwe $, tylko skończoną ilość cycle xs
kiedykolwiek zostanie obliczona ale ten może biec i biec: rotationsL' 10 [1..4]
daje:
[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3],[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3],[1,2,3,4],[2,3,4,1]]
Byłoby miło zrobić prawo w ten sposób również, ale nie działa, ponieważ musiałbym zacząć na końcu nieskończonej listy i wracać do pracy. Załóżmy, ponowne swój rewers, wziąć co trzeba, znowu odwrócić tricka, choć:
rotationsR' n xs = let l = length xs in
take n . map (reverse.take l) . tails . cycle . reverse $ xs
Undigression: Jeśli wolisz trzymać bliżej do oryginalnego kodu, można zrobić
generatingListforRightShifting n xs =
[reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs)) | i <- [1..n]]
to byłoby 'drop', nie t "przesunięcie", które ma być "obrotem". –
@ Daniel Fisher: tak - zdałem sobie sprawę zbyt późno, że w połowie czytałem pytanie. "Rotate" to dobre imię. – xtofl
thnx do u xtolf. Właściwie jako początkujący staram się używać prostych operacji, takich jak głowa, ogon, powtarzanie. Z tego powodu próbuję tego problemu. Nie chcę dnstruować kodu. fllowing portin po takewhile "(reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs)))" działa dla pojedynczego przesunięcia czasowego. Chcę użyć tego do wielokrotnego przesuwania czasu. możesz mi pomóc nw? btw, thx i bardzo bardzo thnx fr ur effrt – sabu