Skip to content

Instantly share code, notes, and snippets.

@samyarkd
Created August 18, 2023 18:33
Show Gist options
  • Save samyarkd/42d8575c3e5c304c2122e16acd9f52ab to your computer and use it in GitHub Desktop.
Save samyarkd/42d8575c3e5c304c2122e16acd9f52ab to your computer and use it in GitHub Desktop.
{-
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) ubitsize (int a) asm "UBITSIZE";
forall T -> int tuple_length(T tup) asm "TLEN";
forall X -> (tuple, ()) push_back (tuple tail, X head) asm "CONS";
forall X -> (tuple, (X)) pop_back (tuple t) asm "UNCONS";
forall X -> (tuple, (X)) tpop_back (tuple t, int k) asm "INDEXVAR";
;; forall X -> (tuple, (X)) un_pair (tuple t) asm "UNPAIR";
forall X -> (tuple, X) ~tpop (tuple t) asm "TPOP";
forall X -> int cast_to_int (X x) asm "NOP";
forall X -> int is_null (X x) asm "ISNULL";
forall X -> int is_int (X x) asm "<{ TRY:<{ 0 PUSHINT ADD DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS";
(int) are_tuples_equal? (tuple t1, tuple t2) {
int equal? = -1; ;; initial value to true
if (t1.tuple_length() != t2.tuple_length()) {
;; if tuples are differ in length they cannot be equal
return 0;
}
int i = t1.tuple_length();
while (i > 0 & equal?) {
var v1 = t1~tpop();
var v2 = t2~tpop();
if (is_int(v1) & is_int(v2)) {
if (cast_to_int(v1) != cast_to_int(v2)) {
equal? = 0;
}
}
else {
equal? = 0;
}
i -= 1;
}
return equal?;
}
() recv_internal() {
}
tuple get_binary_list(cell c) {
tuple list = null();
list~push_back(c);
tuple res = empty_tuple();
while (~ list.is_null()) {
cell current_cell = list~pop_back();
slice current_slice = current_cell.begin_parse();
do {
res~tpush(current_slice~load_uint(1));
} until (current_slice.slice_data_empty?())
repeat (current_slice.slice_refs()) {
list~push_back(current_slice~load_ref());
}
}
return res;
}
(tuple) reverse_tuple (tuple t1) {
tuple t2 = empty_tuple();
repeat (t1.tuple_length()) {
var value = t1~tpop();
t2~tpush(value);
}
return t2;
}
global tuple stack;
(cell) store_data(cell c, tuple flag_t, int value_l, int value) {
slice ds = c.begin_parse();
builder base = begin_cell();
while (~ ds.slice_data_empty?()){
int data = ds~load_uint(1);
stack~tpush(data);
if (stack.tuple_length() == flag_t.tuple_length()) {
int is_e = are_tuples_equal?(stack, flag_t);
if (is_e) {
stack = empty_tuple();
base~store_uint(value, value_l);
} else {
int v = stack~tpop_back(0);
base~store_uint(v, 1);
}
}
}
if (~ ds.slice_refs_empty?()) {
return base.store_ref(store_data(ds~load_ref(), flag_t, value_l, value)).end_cell();
}
if (stack.tuple_length() > 0) {
builder bb = begin_cell();
repeat (stack.tuple_length()) {
int v = stack~tpop_back(0);
bb~store_uint(v, 1);
}
return base.store_ref(bb.end_cell()).end_cell();
}
return base.end_cell();
}
;; testable
(cell) find_and_replace(int flag, int value, cell linked_list) method_id {
int flag_len = ubitsize(flag);
int value_len = ubitsize(value);
tuple flag_t = get_binary_list(begin_cell().store_uint(flag, flag_len).end_cell());
stack = empty_tuple();
cell result = store_data(linked_list, flag_t, value_len, value);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment