-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3.fc
180 lines (158 loc) · 5.17 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
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
{-
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...
-}
() recv_internal() {
}
int builder_remaining_bits(builder b) asm "BREMBITS";
int zero(slice s) asm "SDCNTLEAD0";
int one(slice s) asm "SDCNTLEAD1";
builder sero(builder b, int n) asm "STZEROES";
(int) prefix(slice a, slice b) asm "SDPFX";
(int) ubitsize (int a) asm "UBITSIZE";
;; testable
(cell) find_and_replace(int flag, int value, cell linked_list) method_id {
tuple answers = null();
int tlen = 0;
builder answer = begin_cell();
slice s = linked_list.begin_parse();
if(ubitsize(flag) == 1) {
int loop_flag = -1;
while (loop_flag) {
int zeros = zero(s);
if (zeros != 0) {
int bbits = builder_remaining_bits(answer);
if (zeros >= builder_remaining_bits(answer)) {
tlen += 1;
s~skip_bits(bbits);
answer = sero(answer, bbits);
answers = cons(answer, answers);
zeros -= bbits;
answer = begin_cell().store_slice(s~load_bits(zeros - bbits));
} else {
s~skip_bits(zeros);
answer = sero(answer, zeros);
}
}
if (slice_bits(s) == 0) {
if (slice_refs_empty?(s)) {
loop_flag = 0;
} else {
s = s~load_ref().begin_parse();
}
} else {
int ones = one(s);
s~skip_bits(ones);
repeat (ones) {
if (builder_remaining_bits(answer) >= ubitsize(value)) {
answer = answer.store_uint(value, ubitsize(value));
} else {
answers = cons(answer, answers);
tlen += 1;
answer = begin_cell().store_uint(value, ubitsize(value));
}
}
}
}
if (builder_bits(answer) != 0) {
answers = cons(answer, answers);
tlen += 1;
}
if (tlen == 0) {
return answer.end_cell();
}
(builder item, answers) = uncons(answers);
repeat(tlen - 1) {
(builder item2, answers) = uncons(answers);
item2 = item2.store_ref(item.end_cell());
item = item2;
}
return item.end_cell();
}
int flag_size = ubitsize(flag);
int value_size = ubitsize(value);
slice flag_slice = begin_cell().store_uint(flag, flag_size).end_cell().begin_parse();
slice next = slice_refs(s) > 0 ? s~load_ref().begin_parse() : begin_cell().end_cell().begin_parse();
do {
while(slice_bits(s) >= flag_size) {
if(builder_remaining_bits(answer) <= value_size) {
tlen += 1;
answers = cons(answer, answers);
answer = begin_cell();
}
if(prefix(flag_slice, s) == -1){
s~skip_bits(flag_size);
answer = answer.store_uint(value, value_size);
} else {
int b = s~load_uint(1);
answer = answer.store_uint(b, 1);
}
}
int nb = slice_bits(next);
if(nb == 1023) {
s = begin_cell()
.store_slice(s) ;; maximum flag_size bits
.store_slice(next~load_bits(1023 - flag_size * 2))
.end_cell()
.begin_parse();
} elseif(nb > 420) {
s = begin_cell()
.store_slice(s)
.store_slice(next~load_bits(nb))
.end_cell()
.begin_parse();
} else {
;; flag 60
builder s2 = begin_cell()
.store_slice(s) ;; maximum flag_size bits
.store_slice(next~load_bits(nb)); ;; flag_size * 2 bits
if(slice_refs(next) == 1) {
next = next~load_ref().begin_parse();
nb = slice_bits(next);
;; ~dump(nb);
;; ~dump(builder_remaining_bits(s2));
s2 = nb > 600 ? s2.store_slice(next~load_bits(600)) : s2.store_slice(next~load_bits(nb));
;; ~dump(35);
s = s2.end_cell().begin_parse();
} else {
s = s2.end_cell().begin_parse();
}
}
} until(slice_bits(s) < flag_size);
int nb = slice_bits(s);
if(nb != 0) {
if(builder_remaining_bits(answer) >= nb) {
answer = answer.store_slice(s);
} else {
answers = cons(answer, answers);
tlen += 1;
answer = begin_cell().store_slice(s);
}
}
if(builder_bits(answer) != 0) {
answers = cons(answer, answers);
tlen += 1;
}
if(tlen == 0) {
return answer.end_cell();
}
(builder item, answers) = uncons(answers);
repeat(tlen - 1) {
(builder item2, answers) = uncons(answers);
item2 = item2.store_ref(item.end_cell());
item = item2;
}
return item.end_cell();
}