测试嵌套列表中对角线相邻的元素 [英] Testing diagonally adjacent elements in nested lists

查看:102
本文介绍了测试嵌套列表中对角线相邻的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是对最近的问题的后续行动,该问题尚未明确提出.海报 Aditi Jain 答案早已失效,

This is a followup to a recent question that wasn't asked clearly. The poster Aditi Jain's clarifications invalidate the answer somewhat that's already posted there, hence this new post.

目标是检查嵌套列表中是否没有对角相邻的,彼此为负的元素对. 海报是Haskell编程的新手.

The objective is to check whether there's no diagonally adjacent pair of elements in the nested lists which are negative of one another. The poster is new to Haskell programming.

函数签名为:

checkNegation :: [[Int]] -> Bool

示例:

checkNegation [[1,2], [-2,3]]将返回False:

[ [ 1 ,  2],      -- 2, -2 are diagonally adjacent
  [-2 ,  3] ]

checkNegation [[1,2], [3,-1]]将返回False:

[ [ 1 ,  2],      -- 1, -1 are diagonally adjacent
  [ 3 , -1] ]

checkNegation [[1,2], [-1,3]]将返回True:

[ [ 1 ,  2],      -- no diagonally adjacent negatives
  [-1 ,  3] ]

checkNegation [[0,2,1], [3,1,-2], [3,-1,3]]将返回False:

[ [ 0 ,  2,  1],  -- 2, -2 are diagonally adjacent
  [ 3 ,  1, -2],
  [ 3 , -1,  3] ]

原始帖子中未提供任何编码尝试.

No coding attempts were provided in the original post.

(我不将其标记为CW,以免阻止答复者因其努力而获得声望点)

推荐答案

如果我们逐行处理矩阵,则操作起来会容易一些.例如,以下内容:

It's a little easier to do things if we take the matrix row-by-row. For the following, for instance:

  [a,b,c],
  [d,e,f],

我们只想比较两对:

[(a,e),(b,f),(b,d),(c,e)]

因此,第一步是编写一个从两个相邻行构造该列表的函数.

So the first step is to write a function which constructs that list from two adjacent rows.

diags xs ys = zip xs (drop 1 ys) ++ zip (drop 1 xs) ys

我们使用的是drop 1而不是tail,因为它不会在空白列表上出错,而​​我以后使用此功能的方式将使用空白列表.

We're using drop 1 rather than tail because it doesn't error on the empty list, and the way I'm going to use this function later will use empty lists.

如果我们将其折叠使用,则其外观如下:

If we use this in a fold, then, it looks like the following:

anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p = fst . foldr f (False, [])
  where
    f xs (a, ys) = (a || or (zipWith p xs (drop 1 ys)) || or (zipWith p (drop 1 xs) ys), xs)

我们还使它在任何关系上都通用.

We've also made it generic over any relation.

接下来,我们将要弄清楚如何检查两个数字是否为负数.

Next we will want to figure out how to check if two numbers are negations of each other.

negEachOther x y = negate x == y

然后我们的检查取反函数如下:

And then our check negation function is as follows:

checkNegation = anyDiags negEachOther

在这里,我们可以使用anyDiags函数做一些有趣的事情.实际上有隐藏在其中的writer monad的用法.这样,我们可以重写折叠以使用该事实:

There are some fun things we can do with the anyDiags function here. There's actually a use of the writer monad hidden in it. With that, we can rewrite the fold to use that fact:

anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p = getAny . fst . foldrM f []
  where
    f xs ys = (Any (or (zipWith p xs (drop 1 ys)) || or (zipWith p (drop 1 xs) ys)), xs)

尽管我不确定是否更清晰.

Though I'm not sure if it's any clearer.

或者,我们可以使用zip xs (tail xs)技巧完成整件事:

Alternatively, we could do the whole thing using the zip xs (tail xs) trick:

anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p xs = or (zipWith f xs (tail xs))
  where
    f xs ys = or (zipWith p xs (drop 1 ys)) || or (zipWith p (drop 1 xs) ys)

这篇关于测试嵌套列表中对角线相邻的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆