How to resolve the algorithm Recaman's sequence step by step in the Haskell programming language
Published on 7 June 2024 03:52 AM
How to resolve the algorithm Recaman's sequence step by step in the Haskell programming language
Table of Contents
Problem Statement
The Recamán's sequence generates Natural numbers. Starting from a(0)=0, the n'th term a(n), where n>0, is the previous term minus n i.e a(n) = a(n-1) - n but only if this is both positive and has not been previousely generated. If the conditions don't hold then a(n) = a(n-1) + n.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Recaman's sequence step by step in the Haskell programming language
Haskell is a purely functional programming language and the code snippet you provided is an implementation of the Recaman's sequence using different approaches:
recaman n
: computes the firstn
Recaman's numbers. Recaman's sequence is an infinite sequence of integers starting with 0 and is defined by the following rules:- The first term of the sequence is
0
. - Each subsequent term is obtained by subtracting the previous term from the smallest non-negative integer that has not yet appeared in the sequence.
- If the result of the subtraction is non-negative, then the result is the next term of the sequence.
- Otherwise, the result plus the previous term is the next term of the sequence.
firstNRecamans n
: computes the firstn
Recaman's numbers.firstDuplicateR
: computes the first duplicated Recaman's number.recamanSuperset setInts
: computes the length of the Recaman's series required to include the set of integerssetInts
.recamanUpto p
: computes the Recaman's series up to a predicatep
.nextR seen i r
: computes the next Recaman's number based on the previous Recaman's number, the index, and the set of seen numbers.rSeries
: computes an infinite stream of Recaman's series of growing length.rSets
: computes an infinite stream of Recaman-generated integer sets of growing size.
The main function in the code snippet:
- prints the first 15 Recaman's numbers
- the first duplicated Recaman's number
- the length of the Recaman's series required to include the set of integers [0..1000]
Source code in the haskell programming language
recaman :: Int -> [Int]
recaman n = fst <$> reverse (go n)
where
go 0 = []
go 1 = [(0, 1)]
go x =
let xs@((r, i):_) = go (pred x)
back = r - i
in ( if 0 < back && not (any ((back ==) . fst) xs)
then back
else r + i
, succ i) :
xs
main :: IO ()
main = print $ recaman 15
import Data.Set (Set, fromList, insert, isSubsetOf, member, size)
import Data.Bool (bool)
firstNRecamans :: Int -> [Int]
firstNRecamans n = reverse $ recamanUpto (\(_, i, _) -> n == i)
firstDuplicateR :: Int
firstDuplicateR = head $ recamanUpto (\(rs, _, set) -> size set /= length rs)
recamanSuperset :: Set Int -> [Int]
recamanSuperset setInts =
tail $ recamanUpto (\(_, _, setR) -> isSubsetOf setInts setR)
recamanUpto :: (([Int], Int, Set Int) -> Bool) -> [Int]
recamanUpto p = rs
where
(rs, _, _) =
until
p
(\(rs@(r:_), i, seen) ->
let n = nextR seen i r
in (n : rs, succ i, insert n seen))
([0], 1, fromList [0])
nextR :: Set Int -> Int -> Int -> Int
nextR seen i r =
let back = r - i
in bool back (r + i) (0 > back || member back seen)
-- TEST ---------------------------------------------------------------
main :: IO ()
main =
(putStrLn . unlines)
[ "First 15 Recamans:"
, show $ firstNRecamans 15
, []
, "First duplicated Recaman:"
, show firstDuplicateR
, []
, "Length of Recaman series required to include [0..1000]:"
, (show . length . recamanSuperset) $ fromList [0 .. 1000]
]
import Data.List (find, findIndex, nub)
import Data.Maybe (fromJust)
import Data.Set (Set, fromList, insert, isSubsetOf, member)
--- INFINITE STREAM OF RECAMAN SERIES OF GROWING LENGTH --
rSeries :: [[Int]]
rSeries =
scanl
( \rs@(r : _) i ->
let back = r - i
nxt
| 0 > back || elem back rs = r + i
| otherwise = back
in nxt : rs
)
[0]
[1 ..]
----------- INFINITE STREAM OF RECAMAN-GENERATED ---------
--------------- INTEGER SETS OF GROWING SIZE -------------
rSets :: [(Set Int, Int)]
rSets =
scanl
( \(seen, r) i ->
let back = r - i
nxt
| 0 > back || member back seen = r + i
| otherwise = back
in (insert nxt seen, nxt)
)
(fromList [0], 0)
[1 ..]
--------------------------- TEST -------------------------
main :: IO ()
main = do
let setK = fromList [0 .. 1000]
(putStrLn . unlines)
[ "First 15 Recamans:",
show . reverse . fromJust $ find ((15 ==) . length) rSeries,
[],
"First duplicated Recaman:",
show . head . fromJust $ find ((/=) <$> length <*> (length . nub)) rSeries,
[],
"Length of Recaman series required to include [0..1000]:",
show . fromJust $ findIndex (\(setR, _) -> isSubsetOf setK setR) rSets
]
You may also check:How to resolve the algorithm Find palindromic numbers in both binary and ternary bases step by step in the zkl programming language
You may also check:How to resolve the algorithm Modular inverse step by step in the OCaml programming language
You may also check:How to resolve the algorithm Doubly-linked list/Element insertion step by step in the AutoHotkey programming language
You may also check:How to resolve the algorithm Tree datastructures step by step in the Wren programming language
You may also check:How to resolve the algorithm Permutations/Rank of a permutation step by step in the zkl programming language