Next highest int from digits: Difference between revisions

Content added Content deleted
(→‎{{header|Haskell}}: Added a digit-swap variant and ten digit-shuffle successors for the larger test number)
Line 232: Line 232:


=={{header|Haskell}}==
=={{header|Haskell}}==
Defining a list of all (if any) digit-shuffle successors of a positive integer.
Defining a list of all (if any) digit-shuffle successors of a positive integer,
in terms of permutations.
{{Trans|Python}}
{{Trans|Python}}
(Generator version)
(Generator version)
Line 284: Line 285:
45072010 -> 5 of 1861: [45072100,45100027,45100072,45100207,45100270]
45072010 -> 5 of 1861: [45072100,45100027,45100072,45100207,45100270]
95322020 -> 1 of 1: [95322200]</pre>
95322020 -> 1 of 1: [95322200]</pre>

Or alternatively, defining a lazily-evaluated list of all digit-shuffle successors, this time in terms of minimal digit swaps (rather than the full set of permutations).

(The digit-swap approach makes it feasible to obtain successors of this kind for much larger numbers)

<lang haskell>import Data.List (unfoldr)

digitShuffleSuccessors
:: Integral b
=> b -> [b]
digitShuffleSuccessors n =
let nextDigitPattern = minimalSwap . splitBy (>)
in unDigits <$>
unfoldr
(\ds ->
if null ds
then Nothing
else Just (ds, (nextDigitPattern . reverse) ds))
(nextDigitPattern (reversedDigits n))

minimalSwap
:: Ord a
=> ([a], [a]) -> [a]
minimalSwap ([], x:y:xs) = reverse (y : x : xs)
minimalSwap ([], xs) = []
minimalSwap (_, []) = []
minimalSwap (reversedSuffix, pivot:prefix) =
let (less, h:more) = break (> pivot) reversedSuffix
in reverse (h : prefix) ++ less ++ pivot : more

---------------------------TEST----------------------------
main :: IO ()
main = do
putStrLn $
fTable
"Taking up to 5 digit-shuffle successors of a positive integer:\n"
show
(\xs ->
let harvest = take 5 xs
in rjust
12
' '
(show (length harvest) ++ " of " ++ show (length xs) ++ ": ") ++
show harvest)
digitShuffleSuccessors
[0, 9, 12, 21, 12453, 738440, 45072010, 95322020]
putStrLn $
fTable
"Taking up to 10 digit-shuffle successors of a larger integer:\n"
show
(('\n' :) . unlines . fmap ((" " ++) . show))
(take 10 . digitShuffleSuccessors)
[9589776899767587796600]

--------------------------GENERIC--------------------------
reversedDigits
:: Integral a
=> a -> [a]
reversedDigits 0 = [0]
reversedDigits n = go n
where
go 0 = []
go x = rem x 10 : go (quot x 10)

splitBy :: (a -> a -> Bool) -> [a] -> ([a], [a])
splitBy f xs = go $ break (uncurry f) $ zip xs (tail xs)
where
go (ys, zs)
| null ys = ([], xs)
| null zs = (xs, [])
| otherwise = (fst (head ys) : map snd ys, map snd zs)

unDigits
:: (Foldable t, Num a)
=> t a -> a
unDigits = foldl (\a b -> 10 * a + b) 0

--------------------------DISPLAY--------------------------
fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> String
fTable s xShow fxShow f xs =
unlines $
s : fmap (((++) . rjust w ' ' . xShow) <*> ((" -> " ++) . fxShow . f)) xs
where
w = maximum (length . xShow <$> xs)

rjust :: Int -> Char -> String -> String
rjust n c = drop . length <*> (replicate n c ++)</lang>
{{Out}}
<pre>Taking up to 5 digit-shuffle successors of a positive integer:

0 -> 0 of 0: []
9 -> 0 of 0: []
12 -> 1 of 1: [21]
21 -> 0 of 0: []
12453 -> 5 of 116: [12534,12543,13245,13254,13425]
738440 -> 5 of 96: [740348,740384,740438,740483,740834]
45072010 -> 5 of 1861: [45072100,45100027,45100072,45100207,45100270]
95322020 -> 1 of 1: [95322200]

Taking up to 10 digit-shuffle successors of a larger integer:

9589776899767587796600 ->
9589776899767587900667
9589776899767587900676
9589776899767587900766
9589776899767587906067
9589776899767587906076
9589776899767587906607
9589776899767587906670
9589776899767587906706
9589776899767587906760</pre>


=={{header|Julia}}==
=={{header|Julia}}==