- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
{-# LANGUAGE BangPatterns #-}
import Data.List (intercalate)
-- Тип для представления пары значений
data TwoVal = TwoVal !Int !Int
deriving (Show, Eq)
-- Тип для пары с флагом обмена
data TwoValAndStatus = TwoValAndStatus
{ isSwapped :: !Bool
, twoVal :: !TwoVal
} deriving (Show, Eq)
-- Тип для массива (используем список для идиоматичности Haskell)
type Array = [Int]
-- Тип для массива с состоянием сортировки
data ArrayAndStatus = ArrayAndStatus
{ hasSwap :: !Bool
, position :: !Int
, array :: !Array
} deriving (Show, Eq)
-- Сортировка двух элементов с возвратом статуса обмена
sort2 :: TwoVal -> TwoValAndStatus
sort2 (TwoVal a b)
| a > b = TwoValAndStatus True (TwoVal b a)
| otherwise = TwoValAndStatus False (TwoVal a b)
-- Чтение пары значений из массива по позиции
readTwoVal :: Array -> Int -> Maybe TwoVal
readTwoVal arr pos
| pos < length arr - 1 = Just $ TwoVal (arr !! pos) (arr !! (pos + 1))
| otherwise = Nothing
-- Сохранение значения в массив по индексу
storeVal :: Array -> Int -> Int -> Array
storeVal arr val pos =
take pos arr ++ [val] ++ drop (pos + 1) arr
-- Сохранение пары значений в массив
storeTwoVal :: Array -> TwoVal -> Int -> Array
storeTwoVal arr (TwoVal a b) pos =
storeVal (storeVal arr a pos) b (pos + 1)
-- Рекурсивная функция сортировки пузырьком
bubbleSortRec :: ArrayAndStatus -> ArrayAndStatus
bubbleSortRec state@(ArrayAndStatus swap pos arr)
| pos >= length arr - 1 =
if not swap
then state -- Сортировка завершена!
else bubbleSortRec $ ArrayAndStatus False 0 arr -- Новый проход
| otherwise =
case readTwoVal arr pos of
Nothing -> state
Just pair -> -- ← Переименовали переменную здесь
let sortResult = sort2 pair
newArr = storeTwoVal arr (twoVal sortResult) pos -- ← Используем селектор twoVal
newSwap = swap || isSwapped sortResult
in bubbleSortRec $ ArrayAndStatus newSwap (pos + 1) newArr
-- Основная функция сортировки
bubbleSort :: Array -> Array
bubbleSort arr = array $ bubbleSortRec $ ArrayAndStatus False 0 arr
-- Более идиоматичная версия для Haskell (альтернативная реализация)
bubbleSortIdiomatic :: Ord a => [a] -> [a]
bubbleSortIdiomatic = untilFixed bubblePass
where
bubblePass [] = []
bubblePass [x] = [x]
bubblePass (x:y:xs)
| x > y = y : bubblePass (x:xs)
| otherwise = x : bubblePass (y:xs)
untilFixed f x = let fx = f x
in if fx == x then x else untilFixed f fx
-- Функция для красивого вывода
showArray :: Show a => [a] -> String
showArray = intercalate ", " . map show
-- Главная функция
main :: IO ()
main = do
let initialArray = [8, 2, 4, 1, 3, 5, 7, 0, 6, 9]
let sortedArray = bubbleSort initialArray
putStrLn "input"
putStrLn $ showArray initialArray
putStrLn "\nsort:"
putStrLn $ showArray sortedArray
putStrLn "\nsort2:"
putStrLn $ showArray $ bubbleSortIdiomatic initialArray
Переписал через "ИИ" свою чисто-функциональную сортировку пузырьком на "Haskell". Оригинальный код на Си в https://govnokod.ru/27880#comment755323
Комментарии (2) RSS
Добавить комментарий