You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现findBonding函数,查找列表与二元谓词的合法bonding配对

实现思路判断

你提出的基于foldr的实现思路完全可行,可以精准匹配bonding的所有约束要求。

逻辑简化说明

你给出的5个约束条件可以进一步合并为核心逻辑:

  • 输入列表长度必须为偶数,否则无法满足两两配对要求,直接返回Nothing
  • 需要将列表中所有元素两两匹配为无重叠的配对对,每对(x,y)需满足:
    • x ≠ y
    • p x y = True
  • 最终结果将每个配对对拆分为(x,y)和(y,x)两个元素即可

参考实现代码

import Data.List (elem)

findBonding :: Eq a => (a -> a -> Bool) -> [a] -> Maybe [(a,a)]
findBonding p ls
  -- 长度为奇数无法两两配对,直接返回空
  | odd (length ls) = Nothing
  -- foldr累加器为(已使用元素列表, 已生成配对列表),用Maybe包裹表示是否存在合法解
  | otherwise = fmap snd $ foldr processElem (Just ([], [])) ls
  where
    processElem x (Just (used, pairs))
      -- 当前元素已被配对,直接返回现有结果
      | x `elem` used = Just (used, pairs)
      -- 找未被使用的、符合谓词要求的配对元素
      | otherwise = case filter (\y -> y /= x && not (y `elem` used) && p x y) ls of
          -- 找到匹配元素,标记两个元素为已用,添加双向配对
          (y:_) -> Just (x : y : used, (x,y) : (y,x) : pairs)
          -- 找不到匹配元素,返回Nothing表示无合法解
          [] -> Nothing
    -- 累加器已经是Nothing状态直接传递
    processElem _ Nothing = Nothing

验证测试

调用你给出的测试用例:
findBonding (\x -> \y -> odd(x+y)) [2,3,4,5,6,7]
输出结果为:
Just [(2,3),(3,2),(4,5),(5,4),(6,7),(7,6)]
和预期完全一致。

可选优化点

  • 如果输入列表存在重复元素,建议先调用nub去重后再执行逻辑,避免违反元素唯一出现的约束
  • 如果需要返回所有合法的bonding方案,只需将返回类型改为[[(a,a)]],把Maybe上下文替换为列表上下文即可

内容的提问来源于stack exchange,提问作者GameOwner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 00:15:00