2012-10-24 15 views
5

最近問題があります。そして、この場合私はいくつかの問題を抱えています。要素をn回右にシフトしたリストを生成する

Input: generatingListforRightShifting 2 [1,2,3,4,5,6,7,8] 
Output: [[1,2,3,4,5,6,7,8],[8,1,2,3,4,5,6,7],[7,8,1,2,3,4,5,6]] 

あなたが理解しているように、このプログラムは要素を正しい方向にシフトします。第1引数はシフトを何回行うかを示します。 初心者として、よく知られているリスト機能をいくつか解決しようとしています。再帰を使用します。しかし、私には再帰のアイデアは明確ではありません。私のコードは:

generatingListforRightShifting' _ []=[] 
generatingListforRightShifting' 0 x=x 
generatingListforRightShifting' n xs= newList where 
         newList=takeWhile(\i->[1..n] 
              <=n)(reverse(take 
              i(reverse xs))++reverse(drop i(reverse xs))) 

私がやっている主な間違いは部分的に取ることがわかります。しかし、どのようにn回繰り返すことができますか?私はすでに のようなシフトされた結果を直接表示するプログラムを作成しました入力:generatingListforRightShifting 2 [1,2,3,4,5,6,7,8] 出力:[7,8,1,2,3、 4,5,6] しかし、私が前のすべてのシフトを取得しようとすると私はできません。

誰でも私をここで助けることができます。あなたが私に解決策を教えてくれれば歓迎します。

答えて

2

「シフト」は再帰的に定義できます。shift 0はノーオペレーションで、shift 1+n (x:xs)shift n xsです。等

何か:

shift 0 = \x -> x 
shift n = \[email protected](x:xs) -> (shift (n-1) xs) 

-- example: 
sh3 = shift 3   

そして '回転' の問題が容易になる。

rotate n = \lst -> (shift lst) ++ (take n lst) 
+0

'drop'であろうと、無「シフト」は「回転」を意味する。 –

+0

@ダニエルフィッシャー:うん - 私はあまりにも遅く、質問を半分読んだことを知った。 「回転」はいい名前です。 – xtofl

+0

thnx to u xtolf。実際に初心者として、私は頭、尾、繰り返しのような単純な操作を使用しようとします。このため、私はこの問題を試しています。私はコードを大幅に変更したくない。 "逆方向(逆方向xs)++反転(逆方向i(逆方向xs))")は単一の時間シフトのために働く。私は複数の時間シフトのためにこれを使いたい。あなたは私を助けてくれますか? btw、thxと非常に非常にthnx fr ur effrt – sabu

3

。これは、より一般的に、回転の代わりにシフトとして知られています。 last elementsublist of all elements but the lastを取得する方法があるので、リストを一回回転させるのは簡単です。

rotateOnce lst = (last lst):(init lst) 

また、rotateOnceを2回呼び出すのと同じことに注意してください。したがって、この方法は、前の結果から再帰として単に実施することができる:

rotateN 0 lst = [lst] 
rotateN n lst = lst : rotateN (n-1) ((last lst):(init lst)) 

(注:それは最適な解決策ではないかもしれない)

+3

take(n + 1)$ iterate rotateOnce lst'、あなたが私に尋ねるなら。 –

+0

thnxケニー。しかし、私は私の服用量を十分に冷やしたいと思っていませんでした。私はtakewhileの部分を編集したい。要素をシフトさせるために、この "逆方向(逆方向(逆方向xs))++反転(ドロップn(逆方向xs)))"が実行される。今私は再帰呼び出しなしでこの部分を複数回使いたいと思う。 Thnxたくさん......しかし、私を助けることができますか? – sabu

1

私は非常にある現在のアプローチを落とすことになります畳んだ。代わりに、操作のさまざまなコンポーネントを抽象化することに焦点を合わせます。操作を部分的に分割すると、リストが左に回転し、リストが右に回転するという2つの対称的なコンポーネントがあることがわかります。定義する操作によって、指定された回数だけ右ローテーションが繰り返し実行されます。これは、所望の動作が反復が右回転を左またはいずれかのの指定された数をとるによって定義することができることを示唆しています。例えば、ここにcycleを使用して

left :: [a] -> [a] 
left [] = [] 
left xs = tail xs ++ [head xs] 

right :: [a] -> [a] 
right [] = [] 
right xs = last xs : init xs 

shiftL :: Int -> [a] -> [[a]] 
shiftL n = take n . iterate left 

shiftR :: Int -> [a] -> [[a]] 
shiftR n = take n . iterate right 
+0

3行目で、あなたは頭部xsではなく頭部xsが必要だと思います。 – mhwombat

+0

、ありがとう。 correctnesのために編集されました。 – danportin

1

がいいようだ:

shifts n xs = take (n+1) $ shifts' (cycle xs) 
    where 
    len = length xs 
    shifts' ys = take len ys:shifts' (drop (len-1) ys) 
+0

thnxはです。しかし、urプログラムはエラーを表示します。 – sabu

+0

@SaugataBose申し訳ありません、それを修正しました。 – is7s

2

あなたは私たちが再び起動し、そう のは、あなたのコードを見てみましょうよりも、あなたのコードを修正することを好むように見えます。まず、メインリストチョッピング:

reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs)) 

reverse (take i (reverse xs))は、リストの末尾からi要素を取る いますが、これを達成するために二度リストを逆にし、 drop (length xs - i) xsを行う方が良いでしょう。同様に、reverse (drop i (reverse xs)))take (length xs - i) xsとして実装できます。それは、それが動作することはできませんn、とリスト[1..n] を比較するため、今すぐあなたのコード\i->[1..n]<=nは意味がありません。私たちに

drop (length xs - i) xs ++ take (length xs - i) xs 

を与えます。 i1からnまで実行されるループを作成しようとしていると思います。これは良い計画です。我々は望んでいたものを取得するには、リストの内包表記を使用してみましょう:

[drop (length xs - i) xs ++ take (length xs - i) xs | i <- [1 .. length xs], i <= n] 

が、今、私たちはより良い

[drop (length xs - i) xs ++ take (length xs - i) xs | i <- [1..n]] 
を書かされるであろう1からリストの長さに実行されているが、 n上の数字を捨て、 ています

これにより、nlength xs以上になりますが、そこに大きな問題はありません。最初に確認できました。

お知らせ今、我々は唯一の形(length xs - i)iを使用している、と本当に我々は我々がすべきなので、代わりに1からni実行をさせると、 length xs - iを使用するよりも length xs非常に多くの詳細を再計算していること、

ため例えば [6,5..1] == [6,5,4,3,2,1]

作品
[drop j xs ++ take j xs | j <- [length xs,length xs - 1 .. length xs - n]] 

:私たちはちょうどlength xslength xs - nからj=length xs -iのでjの実行を持っていない理由

あなたが算術演算をしたいより多くのtakeたい

let l = length xs in 
    [drop j xs ++ take j xs | j <- [l,l - 1 .. l - n]] 

または多分あなたを行うには滑らかな印象になりますので、私たちは使用することができます

あなたを停止する追加の利点を持っている
let l = length xs in 
    take n [drop j xs ++ take j xs | j <- [l,l - 1 .. 0]] 

あまりにも多くをして、あなたが最初に戻るときにあなたを あなたが停止する。

私はrotationsR 6 [1..4] == [[1,2,3,4],[4,1,2,3],[3,4,1,2],[2,3,4,1],[1,2,3,4]]を与える

rotationsR n xs = let l = length xs in 
    take n [drop j xs ++ take j xs | j <- [l,l - 1 ..]] 

を与え、generatingListforRightShiftingからrotationsRにあなたの関数の名前を変更したいです。

左回転が簡単になります。

rotationsL n xs = take n [drop j xs ++ take j xs | j <- [0..length xs]] 

余談:私は申し訳ありませんが、自分自身を助けることができなかった、と私は再び始まりました。

私はまだすべてがドロップを好きではないし、一つ一つの時間を取って、私はむしろ隣同士(cycle xs)へxsの 無限に多くのコピーを開くとにそれらすべてをチョッピング無限というの 多くtailsを取ると思います最初のnを与えてください:

ローテーションL 'n xs = l =長さxsを で取る。マップ(take l)。尾。そのため、遅延評価のサイクルの$ XS

cycle xsの唯一の有限量がこれまでに計算されます、 が、この1つは実行し、実行することができます:rotationsL' 10 [1..4]はあなたを与える:

[[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]] 

権利を行うにはいいだろうあまりにも多くのローテーションがありますが、それはうまくいきません。 私は無限のリストの終わりに始まり、帰り道に戻る必要があります。

rotationsR' n xs = let l = length xs in 
    take n . map (reverse.take l) . tails . cycle . reverse $ xs 

Undigressionを:しかし、再びトリックを逆に、あなたが必要なものを取る、のは、 あなたの逆を再利用してみましょうあなたは、むしろ自分の元のコードに、より密接に固執したい場合は、

generatingListforRightShifting n xs = 
    [reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs)) | i <- [1..n]] 
を行うことができます
1

私はsplitAtを使用して非常にまっすぐ進むことにする左回転を見つける:

import Data.Tuple (swap) 
rotateLeft n = uncurry (++) . swap . splitAt n 

> rotateLeft 2 "Hello World!" 
>>> "llo World!He" 
関連する問題