-
Notifications
You must be signed in to change notification settings - Fork 0
/
3.fc
159 lines (130 loc) · 5.66 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
{-
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) get_bits(int v) inline asm "UBITSIZE";
(builder, slice, int) store_slice_safe(builder b, slice s) asm "STSLICERQ" "NULLSWAPIFNOT";
(builder, slice, int) store_uint1_safe(builder b, int s) asm "PUSHINT 1" "STUXQ" "NULLSWAPIFNOT";
;; GasValue: 27104004
;; Points: 5.636026234423962
;; testable
(cell) find_and_replace(int flag, int value, cell linked_list) method_id {
;; prepare slices from flag and value
int bits = get_bits(flag);
int value_bits = get_bits(value);
slice pattern = begin_cell().store_uint(flag, bits).end_cell().begin_parse();
slice value_s = begin_cell().store_uint(value, value_bits).end_cell().begin_parse();
return find_and_replace_rec(begin_cell(), pattern, value_s, linked_list.begin_parse()).end_cell();
}
;; using prefix compare allows you to make it faster
int fast_compare(slice pattern, slice s) asm "SDPFX";
int lead_zeroes(slice s) asm "SDCNTLEAD0";
(builder) find_and_replace_rec(builder out, slice pattern, slice value, slice cs) {
int bits = pattern.slice_bits();
int remaining = cs.slice_bits() - bits;
while(remaining >= 0) {
;; simple case - have enough bits
if (fast_compare(pattern, cs)) {
cs~skip_bits(bits);
(out, _, int failure) = out.store_slice_safe(value);
if (failure) {
builder next_b = begin_cell().store_slice(value);
return out
.store_ref(find_and_replace_rec(next_b, pattern, value, cs).end_cell());
}
remaining -= bits;
} else {
slice next_bit = cs~load_bits(1);
(out, _, int failure) = out.store_slice_safe(next_bit);
if (failure) {
builder next_b = begin_cell().store_slice(next_bit);
return out
.store_ref(find_and_replace_rec(next_b, pattern, value, cs).end_cell());
}
remaining -= 1;
}
;; lead zeroes could be omited - it is not possible to have flag here
int lz = lead_zeroes(cs);
if (lz > 0) {
slice zeroes = cs~load_bits(lz);
(out, _, int failure) = out.store_slice_safe(zeroes);
if (failure) {
builder next_b = begin_cell().store_slice(zeroes);
return out
.store_ref(find_and_replace_rec(next_b, pattern, value, cs).end_cell());
}
remaining -= lz;
}
};
;; has next cell
if (cs.slice_refs()) {
while(~ cs.slice_data_empty?()) {
;; less then bits avaialable, but > 0
;; has next cell
if (fast_compare(cs, pattern)) { ;; prefix matches
;; if (equal_slice_bits(cs, pattern.first_bits(cs.slice_bits()))) { ;; prefix matches
slice next_cs = cs.preload_ref().begin_parse();
if (next_cs.slice_bits() < bits - cs.slice_bits()) { ;; no bits
(out, _, int failure) = out.store_slice_safe(cs);
if (failure) {
builder next_b = begin_cell().store_slice(cs);
return out.store_ref(begin_cell().store_slice(cs).end_cell());
}
return out;
}
if (fast_compare(pattern.skip_bits(cs.slice_bits()), next_cs)) {
;; if (equal_slice_bits(next_cs.first_bits(bits - cs.slice_bits()), pattern.skip_bits(cs.slice_bits()))) {
builder next_b = begin_cell().store_slice(value);
return out.store_ref(find_and_replace_rec(next_b, pattern, value, next_cs.skip_bits(bits - cs.slice_bits())).end_cell());
} else {
slice next_bit = cs~load_bits(1);
(out, _, int failure) = out.store_slice_safe(next_bit);
if (failure) {
builder next_b = begin_cell().store_slice(next_bit);
return out.store_ref(find_and_replace_rec(next_b, pattern, value, cs).end_cell());
}
}
} else {
slice next_bit = cs~load_bits(1);
(out, _, int failure) = out.store_slice_safe(next_bit);
if (failure) {
builder next_b = begin_cell().store_slice(next_bit);
return out.store_ref(find_and_replace_rec(next_b, pattern, value, cs).end_cell());
}
}
int lz = lead_zeroes(cs);
if (lz > 0) {
slice zeroes = cs~load_bits(lz);
(out, _, int failure) = out.store_slice_safe(zeroes);
if (failure) {
builder next_b = begin_cell().store_slice(zeroes);
return out
.store_ref(find_and_replace_rec(next_b, pattern, value, cs).end_cell());
}
}
}
return out
.store_ref(find_and_replace_rec(begin_cell(), pattern, value, cs.preload_ref().begin_parse()).end_cell());
} else {
(out, _, int failure) = out.store_slice_safe(cs);
if (failure) {
builder next_b = begin_cell().store_slice(cs);
return out.store_ref(begin_cell().store_slice(cs).end_cell());
}
return out;
}
}