Protobuf structure with bytes field - protocol-buffers

There is a protobuf structures
message A {
bytes B = 1;
}
message B {
int32 c = 1;
int64 d = 2;
string x = 3;
}
If we put the bytes of the same encoded proto-buffer in the A.B field
and decode or encode
pseudocode:
newA = &A{}
newB = &B{x:"123",c:1,d:3}
bytes_of_B = marshall(type(B), newB)
newA.B = bytes_of_B
bytes_of_A = marshall(type(A), newA)
pseudocode:
newA = unmarshall(bytes_of_A, type(A))
newB = unmarshall(newA.B, type(B))
how true is this and what may be the consequences of this

At the wire/payload level, this scenario is 100% identical to
message A {
B B = 1;
}
So: no consequences as such, but telling A to expect a B may be more convenient.

Related

How to model objects with comparable fields in protobuf

Given 3 objects A, B and C where:
A and B share a number of fields, but also each have unique fields
all fields of both A and B are in C, which also some extra unique fields
Obviously I could model this in protobuf by creating separate messages for every object:
message A {
uint32 A_B = 1;
uint32 A_C = 2;
}
message B {
uint32 A_B = 1;
uint32 B_C = 2;
}
message C {
uint32 A_B = 1;
uint32 A_C = 2;
uint32 B_C = 3;
uint32 onlyC = 4;
}
But I was wondering whether it makes sense to create a single, generic message for all three objects and add a field that tells me which specific object I'm dealing with?
message Generic {
enum Specific{
A = 1;
B = 2;
C = 3;
}
Specific obj = 1;
uint32 A_B = 2;
uint32 A_C = 3;
uint32 B_C = 4;
uint32 onlyC = 5;
}
I know both options are possible from a technical point of view, but is the second one somehow not according to how things should be done in protobuf?
Note: in my specific case, the objects represent API call argument lists that won't change in the future.

How can I make sure my RNG numbers are unique?

I'm trying to select 2 random items out of a list using the RNG class. The problem is occasionally I get the same 2 numbers and I'd like them to be unique. I tried using a while loop to get another number if the it's the same as the last one but adding even a simple while loop results in an "Exceeded prepaid gas" error. What am I not understanding?
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
for(let i = 0; i < numItemsWanted; i++) {
var r = rng.next()
while (r == rng.last()) {
r = rng.next()
}
newList.push(oldList[r])
}
Working:
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
let r = rng.next()
let last = r + 1
for(let i = 0; i < numItemsWanted; i++) {
newList.push(oldList[r])
last = r
r = rng.next()
while (r == last) {
r = rng.next()
}
}
this is about near-sdk-as, the smart contract development kit for AssemblyScript on the NEAR platform
you can see how RNG is used in this example
https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/ff6cddaa8cac4d8fe29dd1a19b38a6e3c7045363/src/lottery/assembly/lottery.ts#L12-L13
class Lottery {
private chance: f64 = 0.20
play(): bool {
const rng = new RNG<u32>(1, u32.MAX_VALUE);
const roll = rng.next();
logging.log("roll: " + roll.toString());
return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
}
}
and how the constructor is implemented here:
https://github.com/near/near-sdk-as/blob/f3707a1672d6da6f6d6a75cd645f8cbdacdaf495/sdk-core/assembly/math.ts#L152
the first argument is the length of the buffer holding random numbers generated from the seed. you can use the next() method to get more numbers from this buffer with each call
export class RNG<T> {
constructor(len: u32, public max: u32 = 10_000) {
let real_len = len * sizeof<T>();
this.buffer = math.randomBuffer(real_len);
this._last = this.get(0);
}
next(): T {}
}
If you remove the item from oldList once picked, it would be imposible to picked it again.
Another aproach is to shuffle your oldList and then pick the first two items.

Fast GCF algorithm using linked list

I am using a 2 linked list to represent 2 very long integers, each digit occupy one node. I need to compute for their gcf fast but my current algorithm computes for a very long time. Please help me improve it/or if you can suggest other faster algorithms for linked list.
here's my current code:
int findGCD(number **larger, number **small, number **gcdtop){
number *a = *larger, *b = *small, *aptr, *bptr;
printlist(larger);
printlist(small);
int equal = checkEqual(a, b); //traverse through linked list a & b and compare if equal, returns 1 if true
int large=0, borrow=0, adata=0, bdata=0, i=0;
while(equal!=1){
equal = checkEqual(a, b);
if(equal==1) break;
flip(&a); //Flips the linked list
flip(&b);
large = whatGreater(&a, &b); //Checks which linkedlist is greater
flip(&a); //Flip it back
flip(&b);
borrow=0;
//Do repeated subtraction (Euclid's algorithm)
if(large==1){
aptr = a;
bptr = b;
while(a && b){
adata = a->data;
bdata = b->data;
adata = adata - borrow;
if(adata>=bdata){
a->data = (adata-bdata);
borrow=0;
}
else if(adata<bdata){
adata = adata+10;
a->data = (adata-bdata);
borrow = 1;
}
a = a->next;
b = b->next;
}
a = aptr;
b = bptr;
}
else if(large==0){
aptr = a;
bptr = b;
while(a && b){
adata = a->data;
bdata = b->data;
bdata = bdata - borrow;
if(bdata>=adata){
b->data = (bdata-adata);
borrow=0;
}
else if(bdata<adata){
bdata = bdata+10;
b->data = (bdata-adata);
borrow = 1;
}
a = a->next;
b = b->next;
}
a = aptr;
b = bptr;
}
}
I believe doing this division/modulo would be faster but I cannot implement it in linked list.
Here's a sample input: 15424832369192002264032565635067237193339888184999832384884463019917546384661904, 65227
Thank you in advance.

Sorting Structures

Basically I need to sort arrays of structs by value from highest to lowest.
I must read from file into structure and then sort it.
Initial information:
6
m k 250
f k 280
m p 240
f p 290
m s 63
f s 45
My attempt: (sorting part might be incorrect)
using namespace std;
struct clothes
{
char gender;
char type;
int price;
};
int main()
{
ifstream file("duomenys.txt");
int amount;
int end;
file >> amount;
end = amount;
clothes robe[amount];
for(int x = 0; x<amount; x++)
{
file >> robe[x].gender >> robe[x].type >> robe[x].price;
}
for(int x = amount - 1; x>0; x--)
{
for(int i = 0; i < end; i++)
{
if(robe[i].price > robe[i+1].price)
{
???
}
}
end--;
}
return 0;
}
I'm pretty new in programming so please keep your answer as beginner-friendly as possible as I don't know much.
How do I swap information between struct robe[0] and robe[1] and sort them after checking if price is higher ?
#Beta
So I came up with something that worked, I declared additional struct which I used for holding values while swapping, and then swapped each value (gender, type, price) seperately into holder seperately.
robeH.genderH = robe[i].gender;
robe[i].gender = robe[i+1].gender;
robe[i+1].gender = robeH.genderH;
robeH.typeH = robe[i].type;
robe[i].type = robe[i+1].type;
robe[i+1].type = robeH.typeH;
robeH.priceH = robe[i].price;
robe[i].price = robe[i+1].price;
robe[i+1].price = robeH.priceH;
Thanks for help
P.S. Is it good practice to do it like I did or is there better way

Multiplication of very long integers

Is there an algorithm for accurately multiplying two arbitrarily long integers together? The language I am working with is limited to 64-bit unsigned integer length (maximum integer size of 18446744073709551615). Realistically, I would like to be able to do this by breaking up each number, processing them somehow using the unsigned 64-bit integers, and then being able to put them back together in to a string (which would solve the issue of multiplied result storage).
Any ideas?
Most languages have functions or libraries that do this, usually called a Bignum library (GMP is a good one.)
If you want to do it yourself, I would do it the same way that people do long multiplication on paper. To do this you could either work with strings containing the number, or do it in binary using bitwise operations.
Example:
45
x67
---
315
+270
----
585
Or in binary:
101
x101
----
101
000
+101
------
11001
Edit: After doing it in binary I realized that it would be much simpler (and faster of course) to code using bitwise operations instead of strings containing the base-10 numbers. I've edited my binary multiplying example to show a pattern: for each 1-bit in the bottom number, add the top number, bit-shifted left the position of the 1-bit times to a variable. At the end, that variable will contain the product.
To store the product, you'll have to have two 64-bit numbers and imagine one of them being the first 64 bits and the other one the second 64 bits of the product. You'll have to write code that carries the addition from bit 63 of the second number to bit 0 of the first number.
If you can't use an existing bignum library like GMP, check out Wikipedia's article on binary multiplication with computers. There are a number of good, efficient algorithms for this.
The simplest way would be to use the schoolbook mechanism, splitting your arbitrarily sized numbers into chunks of 32-bit each.
Given A B C D * E F G H (each chunk 32-bit, for a total 128 bit)
You need an output array 9 dwords wide.
Set Out[0..8] to 0
You'd start by doing: H * D + out[8] => 64 bit result.
Store the low 32-bits in out[8] and take the high 32-bits as carry
Next: (H * C) + out[7] + carry
Again, store low 32-bit in out[7], use the high 32-bits as carry
after doing H*A + out[4] + carry, you need to continue looping until you have no carry.
Then repeat with G, F, E.
For G, you'd start at out[7] instead of out[8], and so forth.
Finally, walk through and convert the large integer into digits (which will require a "divide large number by a single word" routine)
Yes, you do it using a datatype that is effectively a string of digits (just like a normal 'string' is a string of characters). How you do this is highly language-dependent. For instance, Java uses BigDecimal. What language are you using?
This is often given as a homework assignment. The algorithm you learned in grade school will work. Use a library (several are mentioned in other posts) if you need this for a real application.
Here is my code piece in C. Good old multiply method
char *multiply(char s1[], char s2[]) {
int l1 = strlen(s1);
int l2 = strlen(s2);
int i, j, k = 0, c = 0;
char *r = (char *) malloc (l1+l2+1); // add one byte for the zero terminating string
int temp;
strrev(s1);
strrev(s2);
for (i = 0;i <l1+l2; i++) {
r[i] = 0 + '0';
}
for (i = 0; i <l1; i ++) {
c = 0; k = i;
for (j = 0; j < l2; j++) {
temp = get_int(s1[i]) * get_int(s2[j]);
temp = temp + c + get_int(r[k]);
c = temp /10;
r[k] = temp%10 + '0';
k++;
}
if (c!=0) {
r[k] = c + '0';
k++;
}
}
r[k] = '\0';
strrev(r);
return r;
}
//Here is a JavaScript version of an Karatsuba Algorithm running with less time than the usual multiplication method
function range(start, stop, step) {
if (typeof stop == 'undefined') {
// one param defined
stop = start;
start = 0;
}
if (typeof step == 'undefined') {
step = 1;
}
if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
return [];
}
var result = [];
for (var i = start; step > 0 ? i < stop : i > stop; i += step) {
result.push(i);
}
return result;
};
function zeroPad(numberString, zeros, left = true) {
//Return the string with zeros added to the left or right.
for (var i in range(zeros)) {
if (left)
numberString = '0' + numberString
else
numberString = numberString + '0'
}
return numberString
}
function largeMultiplication(x, y) {
x = x.toString();
y = y.toString();
if (x.length == 1 && y.length == 1)
return parseInt(x) * parseInt(y)
if (x.length < y.length)
x = zeroPad(x, y.length - x.length);
else
y = zeroPad(y, x.length - y.length);
n = x.length
j = Math.floor(n/2);
//for odd digit integers
if ( n % 2 != 0)
j += 1
var BZeroPadding = n - j
var AZeroPadding = BZeroPadding * 2
a = parseInt(x.substring(0,j));
b = parseInt(x.substring(j));
c = parseInt(y.substring(0,j));
d = parseInt(y.substring(j));
//recursively calculate
ac = largeMultiplication(a, c)
bd = largeMultiplication(b, d)
k = largeMultiplication(a + b, c + d)
A = parseInt(zeroPad(ac.toString(), AZeroPadding, false))
B = parseInt(zeroPad((k - ac - bd).toString(), BZeroPadding, false))
return A + B + bd
}
//testing the function here
example = largeMultiplication(12, 34)
console.log(example)

Resources