-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmem.mdtlbl
300 lines (262 loc) · 7.27 KB
/
mem.mdtlbl
1
2
3
4
5
6
7
8
9
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
const Memory = cell1; # Read/Write默认实现的读写目标
const Read = (__:
#**
使用read读取Memory中的Index处, 读取到RES中, 这里假定传入RES不为`$`
*#
take Index = _0;
take RES = _1;
setres RES;
read $ Memory Index;
);
const Write = (__:
#**
使用write向Memory中的Index写入Data
获取Data时会传入Index
*#
take Index = _0;
take[Index] Data = _1; # 会传入下标, 满足一部分需求
write Data Memory Index;
);
const SwapMem = (
#**
交换两个内存中两个位置的值
返回句柄为交换前Index1的值
*#
take Cell1 = _0;
take Cell2 = _1;
take Index1 = _2;
take Index2 = _3;
take Tmp1 = $; # 用于交换的中间变量
take Tmp2 = ();
read Tmp1 Cell1 Index1;
read Tmp2 Cell2 Index2;
write Tmp2 Cell1 Index1;
write Tmp1 Cell2 Index2;
);
const Swap = (
#**
交换两个位置的值, 使用Read/Write
返回句柄为交换前Index1位置的值
*#
take Index1 = _0;
take Index2 = _1;
take Res = $;
take[Index1 Res] Num1 = Read;
take[Index2 ()] Num2 = Read;
take[Index1 Num2] Write;
take[Index2 Num1] Write;
);
const Reverse = (__:
#**
对[Left,Right]区间的值反转, 使用Read/Write
*#
take Left = _0;
take Right = _1;
take I = ();
take J = ();
I J = Left, Right;
while I < J {
take[I J] Swap;
op I I + 1;
op J J - 1;
}
);
const Fill = (__:
#**
使用Read/Write从Start到End(不包括)的区域使用Value进行填充
这不会预先使用take对Value进行求值, 也就是说你可以使用DExp进行填充
如果你使用DExp来进行填充, 你将会在`_0`接受到当前下标
*#
const Value = _0;
take Start = _1;
take End = _2;
take I = ();
I = Start;
while I < End {
take[I Value] Write;
op I I + 1;
}
);
const Swaps = (__:
#**
使用手摇算法将[LL,LR]与[RL,RR]两个区间的元素进行交换
反转元素使用Reverse
*#
take LL = _0;
take LR = _1;
take RL = _2;
take RR = _3;
take[LL LR] Reverse;
take[RL RR] Reverse;
take[(op $ LR + 1;) (op $ RL - 1;)] Reverse;
take[LL RR] Reverse;
);
const RWhile = (__:
# 使用Read/Write将[a, b]区间进行一次距离为一的向右循环
# 并且在空出的空位写入num
take A = _0;
take B = _1;
take Num = _2;
take I = ();
take J = ();
I = B;
while I > A {
op J I - 1;
take[J ()] Num_1 = Read;
take[I Num_1] Write;
I = J;
}
take[A Num] Write;
);
const Middle = (
#**
获取A与B之间的中间值, 0 <= A <= B
公式为 A + ((B - A) >> 1)
但是由于`Mindustry`中数字都是`double`, 所以不用担心啥中间溢出
并且单条运算效率都相等
故而将其改为 `(A + B) // 2`, 还少了一条`op`
*#
take A = _0;
take B = _1;
#op $ A + (op $ B - A; op $ $ >> 1;);
$ = (A + B) // 2;
);
const BinarySearchInsertIndex = (
#**
对`Start..Stop`也就是包含Start不包含Stop的区间进行二分查找
查找出需要插入的位置, 如果没找到返回值应为Stop
如果是`[0, 2, 3]`查找1, 则返回`1`也就是`2`的位置
如果是`[0, 2, 3]`查找2, 则返回`2`也就是`3`的位置, 因为需要在3的位置插入2
这需要被查找区间内元素有序
Key是用来取用于比较的key的, 如果你并不想处理那直接传入`(_0:)`即可
Num是已经使用Key求值之后的数据
注: 使用Read进行读取
*#
take Num = _0;
const Key = _1;
take Start = _2;
take Stop = _3;
take I = $;
take J = ();
I J = Start, Stop;
while I < J {
take[I J] Mid = Middle;
take[Mid ()] Tmp = Read;
take[Tmp] KeyedTmp = Key;
if KeyedTmp > Num {
J = Mid;
} else {
op I Mid + 1;
}
}
# result `I`
);
const BinaryInsertSort = (__:
#**
二分插入排序算法, 在Cell中对Start..Stop范围中进行二分插入排序
Key是用来取用于比较的key的, 如果你并不想处理那直接传入`(_0:)`即可
注: 使用Read/Write进行读写
*#
const Key = _0;
take Start = _1;
take Stop = _2;
take I = ();
op I Start + 1;
while I < Stop {
take[I ()] Num = Read;
take[Num] KeyedNum = Key;
take[KeyedNum Key Start I Cell] InsertPoint = BinarySearchInsertIndex;
take[InsertPoint I Num Cell] RWhile;
op I I + 1;
}
);
const InsertSort = (__:
#**
插入排序算法, 在Cell中对Start..Stop范围中进行二分插入排序
Key是用来取用于比较的key的, 如果你并不想处理那直接传入`(_0:)`即可
注: 使用Read/Write进行读写
*#
const Key = _0;
take Start = _1;
take Stop = _2;
take I = ();
take J = ();
take Tmp = ();
take KeyedPeekNum = ();
op I Start + 1;
while I < Stop {
take[I ()] Num = Read;
take[Num] KeyedNum = Key;
J = I;
while (Tmp: $ = J; op J J - 1;) > Start {
take[J ()] PeekNum = Read;
take[PeekNum] KeyedPeekNum = Key;
break ! KeyedPeekNum > KeyedNum;
take[Tmp PeekNum] Write;
}
take[Tmp Num] Write;
op I I + 1;
}
);
const QUICK_SORT_USE_INSERT_SORT_LEN = 10;
const QuickSort = (__:
#**
* 简易快速排序, LL版本.
* 当区间长度短于阈值时, 会采用插入排序.
* # params
* * Left: 排序区间的起始
* * Right: 排序区间的终止(包含在内)
* * Stack: 辅助栈内存
* * StackFloor: 辅助栈内存的最低地址
* * Key: 用于排序的键
*#
take Left = _0;
take Right = _1;
take Stack = _2;
take StackFloor = _3;
const Key = _4;
take StackTop = ($ = StackFloor;);
take FuncSize = 2;
const PushParam = (__:
take Left = _0;
take Right = _1;
write Left Stack StackTop;
write Right Stack ($ = StackTop + 1;);
op StackTop StackTop + FuncSize;
);
const PopParam = (__:
take Left = _0;
take Right = _1;
read Left Stack ($ = StackTop - 2;);
read Right Stack ($ = StackTop - 1;);
op StackTop StackTop - FuncSize;
);
take PushParam[Left Right];
while StackTop > StackFloor {
take Left = ();
take Right = ();
take PopParam[Left Right];
if ($ = Right - Left;) < QUICK_SORT_USE_INSERT_SORT_LEN {
take InsertSort[Key Left ($ = Right + 1;)];
} else while Left < Right {
take PivotI = ($ = Left + rand(Right - Left););
take Pivot = Swap[PivotI Right];
take PivotK = Key[Pivot];
take I = ($ = Left;);
take J = ($ = Left;);
while I < Right {
take Num = Read[I ()];
if Key[Num] < PivotK {
take Write[I Read[J ()]];
take Write[J Num];
op J J + 1;
}
op I I + 1;
}
take Write[Right Read[J ()]];
take Write[J Pivot];
take PushParam[($ = J + 1;) Right];
Right = J - 1; # 左递归
}
}
);