P48 - n 元布尔函数真值表

2026-09-07 00:00    #Haskell   #99题   #逻辑  

P48 - n 元布尔函数真值表

Truth tables for n-ary boolean functions

官方模块:Problems.P48 核心函数:tablen


← P47 通用逻辑门 | P49 格雷码 →


题目描述

把 P46 推广到 nn 个变量。每行用前 nn 个布尔值表示输入,最后一个布尔值表示函数结果。

函数签名

1tablen :: Int -> ([Bool] -> Bool) -> [[Bool]]

实现

方法一:递归生成赋值

1tablen :: Int -> ([Bool] -> Bool) -> [[Bool]]
2tablen n f = [xs ++ [f xs] | xs <- assignments n]
3
4assignments :: Int -> [[Bool]]
5assignments 0 = [[]]
6assignments n
7  | n < 0     = []
8  | otherwise = [x : xs | x <- [False, True], xs <- assignments (n - 1)]

assignments n 生成所有 2n2^n 组输入,然后对每组计算 f(xs)f(xs) 并追加到末尾。

方法二:使用 replicateM

1import Control.Monad (replicateM)
2
3tablen :: Int -> ([Bool] -> Bool) -> [[Bool]]
4tablen n f
5  | n < 0     = []
6  | otherwise = [xs ++ [f xs] | xs <- replicateM n [False, True]]

replicateM n [False, True] = 从集合 {False, True} 中选取 n 个元素的所有排列,正好是二进制计数的所有组合。

方法三:用整数位运算生成

1import Data.Bits ((.&.), shiftR)
2
3tablen :: Int -> ([Bool] -> Bool) -> [[Bool]]
4tablen n f
5  | n < 0     = []
6  | otherwise = [bits i ++ [f (bits i)] | i <- [0..2^n - 1]]
7  where
8    bits :: Int -> [Bool]
9    bits i = [((i `shiftR` j) .&. 1) == 1 | j <- [n-1, n-2 .. 0]]

用整数 i 的二进制位生成每组输入。适合对位运算熟悉的读者。

方法对比

方法代码量特点
递归 assignments~5 行自包含,不依赖外部函数
replicateM2 行最简洁,推荐
整数位运算3 行最抽象,适合位运算爱好者

测试

1>>> tablen 2 (\[a,b] -> a && b)
2[[False,False,False],[False,True,False],[True,False,False],[True,True,True]]

参考