Explorar el Código

let's have some fun with data structures.

Lucas Stadler %!s(int64=11) %!d(string=hace) años
padre
commit
a6a5ab84c6
Se han modificado 1 ficheros con 135 adiciones y 0 borrados
  1. 135 0
      hs/DataStructures.hs

+ 135 - 0
hs/DataStructures.hs

@ -0,0 +1,135 @@
1
module DataStructures where
2
3
import Prelude hiding (concat, drop, last, length, reverse, take)
4
5
class Seq s where
6
    first :: s a -> Maybe a
7
8
    last :: s a -> Maybe a
9
    last s | isEmpty s = Nothing
10
    last s | isEmpty (rest s) = 
11
        case first s of
12
            Just x -> Just x
13
    last s = last $ rest s
14
15
    cons :: a -> s a -> s a
16
    nil :: s a
17
18
    rest :: s a -> s a
19
20
    length :: s a -> Integer
21
    length s | isEmpty s = 0
22
    length s = 1 + length (rest s)
23
24
    isEmpty  :: s a -> Bool
25
26
fromList :: (Seq s) => [a] -> s a
27
fromList [] = nil
28
fromList (x:xs) = cons x $ fromList xs
29
30
butLast :: (Seq s) => s a -> s a
31
butLast s | isEmpty s = nil
32
butLast s =
33
    case first s of
34
        Just x -> cons x $ butLast (rest s)
35
36
drop :: (Seq s) => Integer -> s a -> s a
37
drop 0 s = s
38
drop _ s | isEmpty s = nil
39
drop n s = drop (n-1) $ rest s
40
41
take :: (Seq s) => Integer -> s a -> s a
42
take 0 _ = nil
43
take n s =
44
    case first s of
45
        Nothing -> nil
46
        Just x -> cons x $ take (n-1) (rest s)
47
48
append :: (Seq s) => a -> s a -> s a
49
append x s | isEmpty s = cons x nil
50
append x s =
51
    case first s of
52
        Just x -> cons x $ append x (rest s)
53
54
concat :: (Seq s) => s a -> s a -> s a
55
concat l r | isEmpty l = r
56
concat l r | isEmpty r = l
57
concat l r =
58
    case first l of
59
        Just x -> cons x $ concat (rest l) r
60
61
reverse :: (Seq s) => s a -> s a
62
reverse s = rev s nil
63
    where rev l r | isEmpty l = r
64
          rev l r =
65
              case first l of
66
                  Nothing -> nil
67
                  Just x -> rev (rest l) $ cons x r
68
69
data List a = Nil | Cons a (List a) deriving Show
70
71
-- first and cons are O(1), everything else is O(n)
72
instance Seq List where
73
    first Nil = Nothing
74
    first (Cons x _) = Just x
75
76
    cons x l = Cons x l
77
    nil = Nil
78
79
    rest Nil = Nil
80
    rest (Cons _ l) = l
81
82
    isEmpty Nil = True
83
    isEmpty _ = False
84
85
-- fifo, remove from front, insert into rear
86
data BankersQueue a = BankersQueue {
87
                          frontSize :: Integer,
88
                          front :: List a,
89
                          rearSize :: Integer,
90
                          rear :: List a
91
                      } deriving (Show)
92
93
enqueue x (BankersQueue fs f rs r) = check $ BankersQueue fs f (rs + 1) (cons x r)
94
95
dequeue (BankersQueue fs Nil         rs Nil) = Nothing
96
dequeue (BankersQueue fs Nil         rs r) = Just (x, check $ BankersQueue fs Nil (rs - 1) r')
97
    where (Just x) = last r
98
          r' = butLast r
99
dequeue (BankersQueue fs (Cons x fr) rs r) =
100
    Just (x, check $ BankersQueue (fs - 1) fr rs r)
101
102
dequeueN 0 q = Nothing
103
dequeueN 1 q = dequeue q >>= \(x, _) -> return x
104
dequeueN n q = dequeue q >>= \(_, q') -> dequeueN (n-1) q'
105
106
check q@(BankersQueue fs f rs r) =
107
    if rs <= fs
108
    then q
109
    else BankersQueue (fs + rs) (f `concat` reverse r) 0 Nil
110
111
instance Seq BankersQueue where
112
    first (BankersQueue _ Nil         _ r) = last r
113
    first (BankersQueue _ (Cons  x _) _ _) = Just x
114
115
    -- O(1) amortized
116
    last (BankersQueue _ f _ Nil) = last f
117
    last (BankersQueue _ _ _ r) = first r
118
119
    cons x q = enqueue x q
120
    nil = BankersQueue 0 Nil 0 Nil
121
122
    rest q | isEmpty q = nil
123
    rest q =
124
        case dequeue q of
125
            Nothing -> nil
126
            Just (_, q') -> q'
127
128
    length (BankersQueue fs _ rs _) = fs + rs
129
130
    isEmpty (BankersQueue _ Nil _ Nil) = True
131
    isEmpty _ = False
132
133
-- examples
134
sl = fromList [1..10] :: List Integer
135
bq = fromList [1..10] :: BankersQueue Integer