haskell - 在 Haskell 中满足某个要求时突破 If-Then
问题描述
我被分配在 Haskell 中编码一个冰雹序列。必须给我一个整数并创建一个以最后一个数字 1 结尾的整数列表,例如。
-- > hailstone 4
-- [4,2,1]
-- > hailstone 6
-- [6,3,10,5,16,8,4,2,1]
-- > hailstone 7
-- [7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]
我的答案最后应该只有一个 1,但是一旦达到 1,我不知道如何跳出循环。
hailstone :: Integer -> [Integer]
hailstone = takeWhile (>=1) . (iterate collatz)
where collatz n = if n == 1
then 1
else if even n
then n `div` 2
else 3*n+1
最后我得到了无限的 1。我怎样才能解决这个问题?
解决方案
您可以使用包 [hackage]takeUntil :: (a -> Bool) -> [a] -> [a]
中的函数。该功能将:utility-ht
取所有元素,直到一个匹配。匹配的元素也被返回。这是与
takeWhile (not . p)
. 它成立takeUntil p xs == fst (breakAfter p xs)
。
所以我们可以用它来包括1
:
import Data.List.HT(takeUntil)
hailstone :: Integer -> [Integer]
hailstone = takeUntil (== 1) . iterate collatz
where collatz 1 = 1
collatz n | even n = div n 2
| otherwise = 3 * n + 1
或者我们可以实现takeUntil
自己:
takeUntil :: (a -> Bool) -> [a] -> [a]
takeUntil p = go
where go [] = []
go (x:xs) | p x = [x]
| otherwise = x : go xs
或折叠:
takeUntil :: (a -> Bool) -> [a] -> [a]
takeUntil p = foldr (\x y -> x : if p x then [] else y) []
对于负数,collatz
可能会陷入无限循环:
Prelude> hailstone (-7)
[-7,-20,-10,-5,-14,-7,-20,-10,-5,-14,-7,-20,-10,-5,-14,-7,-20,-10,-5,-14,
因此,我们可能希望更改所有小于或等于 的数字的条件1
:
hailstone :: Integer -> [Integer]
hailstone = takeUntil (<= 1) . iterate collatz
where collatz 1 = 1
collatz n | even n = div n 2
| otherwise = 3 * n + 1
推荐阅读
- python - Airflow PostgresOperator 仅在与 DAG 相同的文件夹中查找 SQL 文件
- c# - 如何在 Android.Media.Mediaplayer 中播放 webm?(错误(1,-2147483648))
- flowground - 流场原木的保存期限
- excel - Excel VBA 在共享文件中打开时运行代码
- sql - SQL Server:内部联接运行总计
- postgresql - 通过创建数据源与 PostgreSQL 12 连接时出错
- list - 在 ocaml 中打印 int -> int list
- windows-10 - Windows 有时会将 msi 路径记录放在 \HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\ 中。如何禁用该选项?
- powershell - Azure 标记问题
- python - 序列与字母注释的“位置感知”对齐