Skip to content
This repository was archived by the owner on May 22, 2026. It is now read-only.

Commit 7f660c0

Browse files
Merge pull request #11 from RyosukeDTomita/feature/data_structure
feature/data structure
2 parents 0a8a0d8 + 15eb585 commit 7f660c0

10 files changed

Lines changed: 281 additions & 1 deletion

File tree

data_structure/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
## スタック(Stack)
44

55
- Last In First Out でデータを取り出す構造
6-
- データが入るリストとスタックポインタとなる変数を用意してデータを入れた時にスタックポインタを増やして,データを取り出した時にスタックポインタを減らす。
6+
- 逆ポーランド記法(Reverse Polish Notation)の計算に利用される。
7+
8+
### 実装例
9+
10+
- [x] Python
11+
- [x] C
12+
- [x] Haskell: これだけ逆ポーランド記法の例。(Haskellのリストは単方向連結リストとして実装されているためスタックといって差し支えないため、応用例を変わりに実装)
713

814
---
915

data_structure/stack_/rpn.hs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
rpn :: [String] -> [Int]
2+
rpn input = foldl step [] input
3+
where
4+
step :: [Int] -> String -> [Int]
5+
step stack operand =
6+
case operand of
7+
"+" -> let (a : b : rest) = stack in (b + a) : rest
8+
"-" -> let (a : b : rest) = stack in (b - a) : rest
9+
"*" -> let (a : b : rest) = stack in (b * a) : rest
10+
n -> (read :: String -> Int) n : stack
11+
12+
main :: IO ()
13+
main = do
14+
print $ rpn $ words "4 8 + 1 3 + *" -- (4 + 8) * (1 + 3)

data_structure/tree/fingerTree.hs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
-- 以下のdata型の定義はhttps://www.staff.city.ac.uk/~ross/papers/FingerTree.htmlに記載のあるものを流用している。
2+
data FingerTree a
3+
= Empty -- 要素なし
4+
| Single a -- 要素1つ
5+
| Deep (Digit a) (FingerTree (Node a)) (Digit a)
6+
deriving (Show)
7+
8+
-- Finger Tree左右端のバッファ
9+
data Digit a
10+
= One a
11+
| Two a a
12+
| Three a a a
13+
| Four a a a a
14+
deriving (Show)
15+
16+
-- Finger Treeの中間圧縮ノード
17+
data Node a
18+
= Node2 a a
19+
| Node3 a a a
20+
deriving (Show)
21+
22+
-- 以降はそれっぽく作っているだけ。
23+
24+
-- 先頭(左端)追加
25+
(<|) :: a -> FingerTree a -> FingerTree a
26+
x <| Empty = Single x
27+
x <| Single a = Deep (One x) Empty (One a)
28+
-- pr: prefix(Digit)
29+
-- m: middle(Node)
30+
-- sf: suffix(Digit)
31+
x <| Deep pr m sf =
32+
case pr of -- 左端のDigitのサイズで分岐
33+
One a -> Deep (Two x a) m sf
34+
Two a b -> Deep (Three x a b) m sf
35+
Three a b c -> Deep (Four x a b c) m sf
36+
Four a b c d -> Deep (Two x a) (Node3 b c d <| m) sf -- TODO
37+
38+
-- 末尾(右端)追加
39+
(|>) :: FingerTree a -> a -> FingerTree a
40+
Empty |> x = Single x
41+
Single a |> x = Deep (One a) Empty (One x)
42+
-- pr: prefix(Digit)
43+
-- m: middle(Node)
44+
-- sf: suffix(Digit)
45+
Deep pr m sf |> x =
46+
case sf of
47+
One a -> Deep pr m (Two a x)
48+
Two a b -> Deep pr m (Three a b x)
49+
Three a b c -> Deep pr m (Four a b c x)
50+
Four a b c d -> Deep pr (m |> Node3 a b c) (Two d x)
51+
52+
data ViewR a
53+
= EmptyR
54+
| FingerTree a :> a
55+
deriving (Show)
56+
57+
-- 末尾(右端)とりだし
58+
viewR :: FingerTree a -> ViewR a
59+
viewR Empty = EmptyR
60+
viewR (Single x) = Empty :> x
61+
viewR (Deep pr m sf) =
62+
case sf of
63+
One a ->
64+
case viewR m of
65+
EmptyR -> digitToTreeR pr
66+
m' :> Node2 b c -> Deep pr m' (Two b c) :> a
67+
m' :> Node3 b c d -> Deep pr m' (Three b c d) :> a
68+
Two a b -> Deep pr m (One a) :> b
69+
Three a b c -> Deep pr m (Two a b) :> c
70+
Four a b c d -> Deep pr m (Three a b c) :> d
71+
72+
digitToTreeR :: Digit a -> ViewR a
73+
digitToTreeR (One a) = Empty :> a
74+
digitToTreeR (Two a b) = Single a :> b
75+
digitToTreeR (Three a b c) = Deep (One a) Empty (One b) :> c
76+
digitToTreeR (Four a b c d) = Deep (Two a b) Empty (One c) :> d
77+
78+
data ViewL a
79+
= EmptyL
80+
| a :< FingerTree a
81+
deriving (Show)
82+
83+
-- 先頭(左端)取り出し
84+
viewL :: FingerTree a -> ViewL a
85+
viewL Empty = EmptyL
86+
viewL (Single x) = x :< Empty
87+
viewL (Deep pr m sf) =
88+
case pr of
89+
One a ->
90+
case viewL m of
91+
EmptyL -> case digitToTree sf of
92+
b :< t -> a :< (b <| t)
93+
Node2 b c :< m' -> a :< Deep (Two b c) m' sf
94+
Node3 b c d :< m' -> a :< Deep (Three b c d) m' sf
95+
Two a b ->
96+
a :< Deep (One b) m sf
97+
Three a b c ->
98+
a :< Deep (Two b c) m sf
99+
Four a b c d ->
100+
a :< Deep (Three b c d) m sf
101+
102+
-- digitをFingerTreeに変換する (ViewL用)
103+
digitToTree :: Digit a -> ViewL a
104+
digitToTree (One a) = a :< Empty
105+
digitToTree (Two a b) = a :< Single b
106+
digitToTree (Three a b c) = a :< Deep (One b) Empty (One c)
107+
digitToTree (Four a b c d) = a :< Deep (Two b c) Empty (One d)
108+
109+
main :: IO ()
110+
main = do
111+
-- 末尾追加
112+
let addFingerTree = scanl (|>) Empty [1 .. 21]
113+
putStrLn $ unlines $ map show addFingerTree
114+
putStrLn "--------------------------------------"
115+
-- 先頭追加
116+
let addFingerTree' = scanl (flip (<|)) Empty $ reverse [1 .. 21]
117+
putStrLn $ unlines $ map show addFingerTree'
118+
putStrLn "--------------------------------------"
119+
120+
-- 末端から取り出される過程をみる
121+
let testFingerTree = foldl (|>) Empty [1 .. 21]
122+
let removeSteps = scanl (\ft _ -> restL ft) testFingerTree [1 .. 21]
123+
putStrLn $ unlines $ map show removeSteps
124+
putStrLn "--------------------------------------"
125+
126+
-- 先頭から取り出される過程をみる
127+
let testFingerTree = foldl (|>) Empty [1 .. 21]
128+
let removeSteps = scanl (\ft _ -> restL ft) testFingerTree [1 .. 21]
129+
putStrLn $ unlines $ map show removeSteps
130+
131+
-- viewRの結果から残りの木を取り出す
132+
restR :: FingerTree a -> FingerTree a
133+
restR ft = case viewR ft of
134+
EmptyR -> Empty
135+
rest :> _ -> rest
136+
137+
-- viewLの結果から残りの木を取り出す
138+
restL :: FingerTree a -> FingerTree a
139+
restL ft = case viewL ft of
140+
EmptyL -> Empty
141+
_ :< rest -> rest

data_structure/tree/tree.hs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
-- https://www.sampou.org/haskell/article/whyfp.html より
2+
data Tree a = Node a [Tree a]
3+
4+
-- 木のリストに対する畳み込み
5+
redtree ::
6+
(a -> b -> b) -> -- f : node を潰す
7+
(b -> b -> b) -> -- g : cons を潰す
8+
b -> -- a : nil を潰す
9+
Tree a ->
10+
b
11+
redtree f g a (Node label subtrees) =
12+
f label (redtree' f g a subtrees)
13+
14+
-- ツリーのリストを処理する関数
15+
redtree' ::
16+
(a -> b -> b) ->
17+
(b -> b -> b) ->
18+
b ->
19+
[Tree a] ->
20+
b
21+
redtree' f g a (subtree : rest) =
22+
g
23+
(redtree f g a subtree) -- リストのサイズが1に分解して潰す --> f label (redtree' f g a [先頭の木]) ...という流れでredtree' _ _ a [] = aにたどりつく
24+
(redtree' f g a rest) -- 残りで再帰
25+
redtree' _ _ a [] =
26+
a
27+
28+
tree :: Tree Int
29+
tree =
30+
Node
31+
1
32+
( (:)
33+
(Node 2 [])
34+
( (:)
35+
( Node
36+
3
37+
((:) (Node 4 []) [])
38+
)
39+
[]
40+
)
41+
)
42+
43+
sumtree :: (Num a) => Tree a -> a
44+
sumtree tree = redtree (+) (+) 0 tree
45+
46+
labels :: (Num a) => Tree a -> [a]
47+
labels tree = redtree (:) (++) [] tree
48+
49+
maptree :: (a -> b) -> Tree a -> Tree b
50+
maptree f tree = redtree (\label subtrees -> Node (f label) subtrees) (:) [] tree
51+
52+
main :: IO ()
53+
main = do
54+
print $ sumtree tree -- 10
55+
print $ labels tree -- [1, 2, 3, 4]
56+
print $ maptree (* 2) tree

math/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# 数学ぽいやつ
22

3+
## フィボナッチ数列
4+
5+
[fibonacci](./fibonacci/)
6+
7+
---
8+
9+
## ニュートン法による平方根の近似
10+
11+
[newton](./newton/)
12+
13+
---
14+
315
## ユークリッドの互助法
416

17+
[euclidean](./euclidean/)
18+
19+
### 実装例
20+
21+
- [] C
22+
- [] Python
23+
- [x] Haskell
24+
25+
---
26+
527
## エラトステネスのふるい
28+
29+
[eratosthenes](./eratosthenes/)
30+
31+
- [] C
32+
- [] Python
33+
- [x] Haskell
34+
35+
---

math/newton/newtonRoot.hs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
-- https://www.sampou.org/haskell/article/whyfp.html
2+
-- 近似を1つ進める関数
3+
next :: Double -> Double -> Double
4+
next n x = (x + n / x) / 2
5+
6+
-- 許容誤差と近似値よりも差の小さい2つの連続する近似値を探す
7+
within :: Double -> [Double] -> Double
8+
within eps (a : b : rest)
9+
| abs (a - b) <= eps = b -- 絶対誤差
10+
| otherwise = within eps (b : rest)
11+
12+
-- 2つの近似値の比が1に近づくようにして許容誤差よりも小さい2つの連続する近似値を探す
13+
relative :: Double -> [Double] -> Double
14+
relative eps (a : b : rest)
15+
| abs (a - b) <= eps * abs b = b -- abs (a - b) / abs b <= epsを変形したもの。いわゆる相対誤差
16+
| otherwise = relative eps (b : rest)
17+
18+
-- withinを使って平方根をもとめる例
19+
sqrt' :: Double -> Double -> Double -> Double
20+
sqrt' a0 eps n = within eps $ iterate (next n) a0
21+
22+
relativesqrt :: Double -> Double -> Double -> Double
23+
relativesqrt a0 eps n = relative eps $ iterate (next n) a0
24+
25+
main :: IO ()
26+
main = do
27+
let n = fromIntegral 2 -- 平方根を求めたい値
28+
let a0 = fromInteger 1 -- 計算の初期値
29+
let eps = 0.001
30+
let epsRelative = 0.001
31+
print $ take 10 $ iterate (next n) 1
32+
print $ sqrt' a0 eps n
33+
print $ relativesqrt a0 epsRelative n

0 commit comments

Comments
 (0)