1

その行/列の1の数が偶数でない場合、リストのリストで(1から0に)変化する関数が必要です。私はこれらの機能を実行しました:

1) リスト内の行が偶数かどうかを確認します。

  parityLine :: [[Int]] -> [Bool]
  parityLine [] =[]
  parityLine (x:xs)
                |sum(x) `mod` 2 == 0 = True:(parityLine(xs))
                |otherwise = False:(parityLine(xs))

2) リストのリストで対応する要素を合計します。

 sumPositions :: [[Int]] -> [Int]
 sumPositions [] = []
 sumPositions (x:xs) = foldl (zipWith (+)) (repeat 0) (x:xs)

3) リスト内の列が偶数かどうかを確認します。

 parityColumn :: [Int] -> [Bool]
 parityColumn [] = []
 parityColumn (x:xs)
    |head(x:xs) `mod` 2 == 0 = True:parityColumn(xs)
    |otherwise = False:parityColumn(xs)

4) 操作または 2 つのブール値リストを使用します。

 bol :: [Bool] -> [Bool] -> [[Bool]]
 bol  [] _ = []
 bol (x:xs) (y:ys)= (map (||x) (y:ys)):(bol xs (y:ys))

5) 正しいリスト:

 correct :: [[Int]] -> [[Bool]]
 correct [] = []
 correct (x:xs)=(bol(parityLine (x:xs))(parityColumn(sumPositions(x:xs)))) 

だから私が欲しいのは、これcorrectを行う [[Int]]->[[Int]] に関数を変更することです:

    My Int list(x:xs)                 With my correct function applied

    [[0,0,1,1],                            [[True,True,True,True],
     [1,0,1,1],                             [True,True,False,True],
     [0,1,0,1],                             [True,True,True,True]
     [1,1,1,1]]                             [True,True,True,True]]

これで、2 行目の 3 列目が False であることがわかります。そのため、1 の数が偶数になるように 1 を修正する必要があります。そのリストに複数の False がある場合、これらの 1 の 1 つだけを修正します。

その結果、関数が次の値をcorrect返すようにします。

 [[0,0,1,1],
  [1,0,0,1],
  [0,1,0,1],
  [1,1,1,1]]

ありがとう。

4

2 に答える 2

2

私はゼロからではなく、あなたがいるところから答えを出すので、私よりもあなたのやり方でやっています.

まず、単一の要素に対してそれを行いましょう:

leaveIf :: Bool -> Int -> Int
leaveIf yes 0 = if yes then 0 else 1
leaveIf yes 1 = if yes then 1 else 0

(ガードを使用することもできますが、私の電話には縦棒の文字がありません!)

次に、リストのリストに対してそれを行うことができます:

edit :: [[Bool]] -> [[Int]] -> [[Int]]
edit boolss intss = zipWith (zipWith leaveIf) boolss intss

編集: 1 つだけを変更したいので、後続Falseの s をTruesにする方法が必要になります。

makeTrue :: [Bool] -> [Bool]
makeTrue xs = map (const True) xs

機能を使用しましたconst :: a -> b -> a。たとえば、const 5 'c'ちょうど5です。その定義を に短縮できmakeTrue = map (const True)ます。そのように考えることに慣れると、短いバージョンの方が明確であることがわかります。

oneFalse :: [[Bool]] -> [[Bool]]
oneFalse [] = []
oneFalse (xs:xss) = let (trues,falses) = break (==False) xs in
     case falses of 
       [] -> trues:oneFalse xss
       (False:others) -> (trues ++ False : makeTrue others) : map makeTrue xss

(==False)もっと単純に のように書くこともできますがnot、おそらくあまり明確ではありません。例えば

> oneFalse [[True,True,True,True],[True,False,True,False],[True,False,False,True]]
[[True,True,True,True],[True,False,True,True],[True,True,True,True]]

だから今、私たちは持つことができます

editOne :: [[Bool]] -> [[Int]] -> [[Int]]
editOne boolss intss = zipWith (zipWith leaveIf) (oneFalse boolss) intss
于 2012-12-08T11:11:33.750 に答える
2

AndrewC は、s に対応するすべて の s を変更するソリューションを既に提供しています。最初のものだけを修正したい場合は、次の代わりを見つける必要があります。1FalsezipWith

leaveIf ok x = if ok then x else 1 -x

-- Varianto of zipWith, which changes at most one element of the list
modFirst :: Eq b => (a -> b -> b) -> [a] -> [b] -> [b]
modFirst _ [] _ = []
modFirst _ _ [] = []
modFirst f (x:xs) (y:ys) = z : if y == z then modFirst f xs ys else ys
  where z = f x y

edit :: [[Bool]] -> [[Int]] -> [[Int]]
edit boolss intss = modFirst (modFirst leaveIf) boolss intss

correct' :: [[Int]] -> [[Int]]
correct' xss = edit (correct' xss) xss

結果は、すべての行/行に偶数の 1 が含まれるリストのリストとは限りません。

correct' [[0,1,0],[1,1,1],[0,1,0]] = [[1,1,0],[1,1,1],[0,1,0]

すべてのエラーが修正されるまで (つまり、修正点を計算するまで)、数回反復する必要があります。


元のプログラムをかなり単純化できることを付け加えたいと思います(アルゴリズムを変更せずに):

parityLine :: [[Int]] -> [Bool]
parityLine = map (even . sum)

parityColumn :: [Int] -> [Bool]
parityColumn = map even

sumPositions :: [[Int]] -> [Int]
sumPositions = foldl (zipWith (+)) (repeat 0)

bol :: [Bool] -> [Bool] -> [[Bool]]
bol xs ys = map (\x -> map (||x) ys) xs

correct :: [[Int]] -> [[Bool]]
correct xs = bol (parityLine xs) (parityColumn $ sumPositions xs)
于 2012-12-08T12:22:18.347 に答える