-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3.fc
94 lines (83 loc) · 3.52 KB
/
3.fc
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
{-
TASK 3 - Find and replace binary substring
Binary string is represented as a cell linked list: string splitted to chunks,
first chunk stored to the root cell, next one to the cell in ref and so on;
each cell can have only one ref.
Write the method that find and replaces one flags in the binary string
with another value. Flags and values can be can be of any length, but
strictly up to 128 bits. The method must replace every flag it finds.
Flag and the value to be replaced is guaranteed to be greater than 0.
Lets give a simple example. We have the target flag 101110101 and the value
to be written 111111111 as inputs, and a linked list of cells, in which the bit
value of the first cell ends with ...10100001011, and in the ref we have cell that
starts with 10101000111111...
The output should be a linked list where the first
cell ends with ...10100001111, and the second cell starts with 11111000111111...
-}
int bitsize(int n) asm "BITSIZE";
forall X -> (tuple, ()) push_back (tuple tail, X head) asm "CONS";
forall X -> (tuple, (X)) pop_back (tuple t) asm "UNCONS";
int pow2(int n) asm "POW2";
() recv_internal() {
}
;; testable
cell find_and_replace(int flag, int value, cell linked_list) method_id {
slice current = linked_list.begin_parse();
int flag_size = bitsize(flag) - 1;
int value_size = bitsize(value) - 1;
slice value_slice = begin_cell().store_uint(value, value_size).end_cell().begin_parse();
builder result = begin_cell();
tuple result_stack = null();
do {
slice next = current.slice_refs() ? current~load_ref().begin_parse() : null();
while (current.slice_bits()) {
int fragment = null();
if (current.slice_bits() >= flag_size) {
fragment = current.preload_uint(flag_size);
} else {
if (next.null?()) {
fragment = current.preload_uint(current.slice_bits());
} else {
if (next.slice_bits() + current.slice_bits() >= flag_size) {
fragment = current.preload_uint(current.slice_bits()) * pow2(flag_size - current.slice_bits()) + next.preload_uint(flag_size - current.slice_bits());
} else {
fragment = current.preload_uint(current.slice_bits()) * pow2(flag_size - current.slice_bits()) + next.preload_uint(next.slice_bits());
}
}
}
if (fragment == flag) {
if (1023 - result.builder_bits() >= value_size) {
result = result.store_uint(value, value_size);
} else {
if (result.builder_bits() == 1023) {
result_stack~push_back(result);
result = begin_cell().store_uint(value, value_size);
} else {
slice paste = value_slice;
result_stack~push_back(result.store_slice(paste~load_bits(1023 - result.builder_bits())));
result = begin_cell().store_slice(paste);
}
}
if (current.slice_bits() >= flag_size) {
current~load_bits(flag_size);
} else {
next~load_bits(flag_size - current.slice_bits());
current~load_bits(current.slice_bits());
}
} else {
if (1023 - result.builder_bits()) {
result = result.store_slice(current~load_bits(1));
} else {
result_stack~push_back(result);
result = begin_cell().store_slice(current~load_bits(1));
}
}
}
current = next;
} until (current.null?());
while (~ result_stack.null?()) {
builder part = result_stack~pop_back();
result = part.store_ref(result.end_cell());
}
return result.end_cell();
}