0

Haskellでどうやってそれを作ることができるのかわかりません。たとえば、私はそのような行列を持っています

[[1,2],[3,4]]

そして、この行列の各要素のすべての可能な近傍を含むリストのリストを生成したいと考えています。

期待される結果は次のとおりです。

[[1,2],[1,3],[1,4],[2,1],[2,3],[2,4],[3,1],[3,2],[3,4],[4,1],[4,2],[4,3]]

各セルの隣人のコードでリストのリストを作成する関数を作成する方法を知っています:

pos how = [ (0+dx,0+dy) | dx <- [0..(how-2)], dy <- [0..how-1] ] :: [(Int,Int)]
neighbour (x,y) how = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1],
                                      x+dx >= 0, y+dy >= 0, x+dx<=how-2, y+dy <= how-1,
                                      (x,y)/=(x+dx,y+dy) ] :: [(Int,Int)]
all_n how = [ p | x <- pos how, let p = neighbour x how ] :: [[(Int,Int)]]

しかし、私が説明したように動作するように変更することはできません。

4

2 に答える 2

5

あなたが提案したものとは非常に異なるアプローチをスケッチさせてください。隣人について話すとき、 eのd隣人は、要素eから方向dに一歩進んだ要素であると言います。したがって、たとえば、行列では、数値は数値の右隣です。いくつかのライブラリ コードを使用する必要があります。[[1,2],[3,4]]21

import Data.List

最も単純なことから始めましょう: 1 次元リストの右隣を見つけてみましょう。

rightList (x:y:rest) = (x,y) : rightList (y:rest)
rightList _ = []

行列の行を非決定論的に選択し、その行のすべての右隣を見つけることにより、行列内のすべての右隣を見つけることができます。

right m = m >>= rightList

隣人を見つけるための任意の関数を使用して、タプルを逆にすることで反対方向の隣人を見つけるための関数を作成できます。たとえば、左隣は右隣と同じですが、タプル要素が交換されているため、次のようになります。

swap (x,y) = (y,x)
co direction = map swap . direction
left = co right

下隣人はどうですか?実際、下隣は転置行列の右隣です。

down = right . transpose
up   = co down

次に関心のある方向は、右下の隣人です。これは少しトリッキーです。私たちがやろうとしているのは、2 つのリストを並行してたどることですが、1 つずれています。

downRight (xs:ys:rest) = zip xs (drop 1 ys) ++ downRight (ys:rest)
downRight _            = []
upLeft = co downRight

最後の方向が 1 つあります。つまり、右上隣です。行列を逆さまにすると、これらは右下の隣人になります。

upRight  = downRight . reverse
downLeft = co upRight

最後に、すべての近隣を形成するために、非決定論的に近隣の方向を選択し、その方向のすべての近隣を見つけることができます。

allDirections = [right, left, up, down,
                 downRight, upLeft, upRight, downLeft]
neighbors m = allDirections >>= ($m)

出力は指定した順序どおりではありませんが、これはそれほど重要ではないかもしれません。

于 2012-06-29T21:01:58.717 に答える
1

あなたが今持っているコードを修正するために、私はいくつかの質問を提供します。

  • how-2は奇妙なことです。なぜ2減算するのが正しい数なのですか?
  • の型all_nはかなり奇妙です。なぜ関数なのですか?(その引数は何を表しているのですか?) フラットなリストではなく、ネストされたリストを返すのはなぜですか?
  • 1 つのサイズ パラメータのみを追跡しているようですが、行列は 2 次元行列です。なぜこのような食い違いがあるのでしょうか。(幅と高さの両方のパラメーターを持たないのはなぜですか?)
  • 座標を取得したら、マトリックスからその位置にある要素を取得する方法を知っていますか? (ヒント: 関数があります(!!) :: [a] -> Int -> [a]。) 座標のリストがある場合、リスト内の各要素に対してこれを行う方法を知っていますか? (ヒント: 機能がありますmap :: (a -> b) -> ([a] -> [b])。)

幸運を!

于 2012-06-29T21:33:28.797 に答える