Submission #1362279

#TimeUsernameProblemLanguageResultExecution timeMemory
1362279AvianshAlice, Bob, and Circuit (APIO23_abc)C++20
66 / 100
202 ms256152 KiB
#include "abc.h"
#include <bits/stdc++.h>

using namespace std;

// you may find the definitions useful
const int OP_ZERO    = 0;  // f(OP_ZERO,    x0, x1) = 0
const int OP_NOR     = 1;  // f(OP_NOR,     x0, x1) = !(x0 || x1)
const int OP_GREATER = 2;  // f(OP_GREATER, x0, x1) = (x0 > x1)
const int OP_NOT_X1  = 3;  // f(OP_NOT_X1,  x0, x1) = !x1
const int OP_LESS    = 4;  // f(OP_LESS,    x0, x1) = (x0 < x1)
const int OP_NOT_X0  = 5;  // f(OP_NOT_X0,  x0, x1) = !x0
const int OP_XOR     = 6;  // f(OP_XOR,     x0, x1) = (x0 ^ x1)
const int OP_NAND    = 7;  // f(OP_NAND,    x0, x1) = !(x0 && x1)
const int OP_AND     = 8;  // f(OP_AND,     x0, x1) = (x0 && x1)
const int OP_EQUAL   = 9;  // f(OP_EQUAL,   x0, x1) = (x0 == x1)
const int OP_X0      = 10; // f(OP_X0,      x0, x1) = x0
const int OP_GEQ     = 11; // f(OP_GEQ,     x0, x1) = (x0 >= x1)
const int OP_X1      = 12; // f(OP_X1,      x0, x1) = x1
const int OP_LEQ     = 13; // f(OP_LEQ,     x0, x1) = (x0 <= x1)
const int OP_OR      = 14; // f(OP_OR,      x0, x1) = (x0 || x1)
const int OP_ONE     = 15; // f(OP_ONE,     x0, x1) = 1

const int nameSize   = 20;
const int numSize    = 16;

int conv(const char name[]){
    string nam = "";
    for(int i = 0;i<5;i++){
        if(name[i]<='z'&&name[i]>='a'){
            nam+=name[i];
        }
        else{
            break;
        }
    }
    int ans = 0;
    for(char c : nam){
        ans*=27;
        ans+=(c-'a'+1);
    }
    return ans;
}

// Alice
int // returns la
alice(
    /*  in */ const int n,
    /*  in */ const char names[][5],
    /*  in */ const unsigned short numbers[],
    /* out */ bool outputs_alice[]
) {
    int ind = 0;
    for(int i = 0;i<n;i++){
        int name = conv(names[i]);
        for(int j = 0;j<nameSize;j++){
            if((1<<j)&name){
                outputs_alice[ind++]=1;
            }
            else{
                outputs_alice[ind++]=0;
            }
        }
        for(int j = 0;j<numSize;j++){
            if((1<<j)&numbers[i]){
                outputs_alice[ind++]=1;
            }
            else{
                outputs_alice[ind++]=0;
            }
        }
    }
    return ind;
}


// Bob
int // returns lb
bob(
    /*  in */ const int m,
    /*  in */ const char senders[][5],
    /*  in */ const char recipients[][5],
    /* out */ bool outputs_bob[]
) {
    int ind = 0;
    for(int i = 0;i<m;i++){
        int send = conv(senders[i]);
        int recv = conv(recipients[i]);
        for(int j = 0;j<nameSize;j++){
            if((1<<j)&send){
                outputs_bob[ind++]=1;
            }
            else{
                outputs_bob[ind++]=0;
            }
        }
        for(int j = 0;j<nameSize;j++){
            if((1<<j)&recv){
                outputs_bob[ind++]=1;
            }
            else{
                outputs_bob[ind++]=0;
            }
        }
    }
    return ind;
}


// Circuit
int // returns l
circuit(
    /*  in */ const int la,
    /*  in */ const int lb,
    /* out */ int operations[],
    /* out */ int operands[][2],
    /* out */ int outputs_circuit[][16]
) {
    int n = la/(nameSize+numSize);
    int m = lb/(nameSize*2);
    int ind = 0;
    vector<int>people[n];
    vector<int>nums[n];
    for(int i = 0;i<n;i++){
        for(int j = 0;j<nameSize;j++){
            people[i].push_back(ind++);
        }
        for(int j = 0;j<numSize;j++){
            nums[i].push_back(ind++);
        }
    }
    array<vector<int>,2> msgs[m];
    for(int i = 0;i<m;i++){
        for(int j = 0;j<nameSize;j++){
            msgs[i][0].push_back(ind++);
        }
        for(int j = 0;j<nameSize;j++){
            msgs[i][1].push_back(ind++);
        }
    }
    assert(ind==la+lb);
    if(m==0){
        //corner case
        for(int i = 0;i<n;i++){
            for(int j = 0;j<numSize;j++){
                operations[ind]=OP_ZERO;
                operands[ind][0]=0;
                operands[ind][1]=1;
                outputs_circuit[i][j]=ind;
                ind++;
            }
        }
        return ind;
    }
    auto checkEqual = [&] (vector<int>a, vector<int>b){
        assert(a.size()==b.size());
        vector<int>ans(a.size());
        for(int i = 0;i<a.size();i++){
            operations[ind]=OP_EQUAL;
            operands[ind][0] = a[i];
            operands[ind][1] = b[i];
            ans[i]=ind;
            ind++;
        }
        int las = ans[0];
        for(int i = 1;i<ans.size();i++){
            operations[ind]=OP_AND;
            operands[ind][0]=las;
            operands[ind][1]=ans[i];
            las=ind;
            ind++;
        }
        return las;
    };

    auto mult1 = [&] (vector<int>a, int b){
        //if b is 1 puts a else puts 0
        vector<int>ans(a.size());
        for(int i = 0;i<a.size();i++){
            operations[ind]=OP_AND;
            operands[ind][0]=a[i];
            operands[ind][1]=b;
            ans[i]=ind;
            ind++;
        }
        return ans;
    };

    auto orsum = [&] (vector<int>a, vector<int>b){
        assert(a.size()==b.size());
        vector<int>ans(a.size());
        for(int i = 0;i<a.size();i++){
            ans[i]=ind;
            operations[ind]=OP_OR;
            operands[ind][0]=a[i];
            operands[ind][1]=b[i];
            ind++;
        }
        return ans;
    };

    auto add = [&] (vector<int>a, vector<int>b) {
        assert(a.size()==b.size());
        vector<int>ans(a.size());
        ans[0]=ind;
        operations[ind]=OP_XOR;
        operands[ind][0]=a[0];
        operands[ind][1]=b[0];
        ind++;
        int carry = ind;
        operations[ind]=OP_AND;
        operands[ind][0]=a[0];
        operands[ind][1]=b[0];
        ind++;
        for(int i = 1;i<ans.size();i++){
            operations[ind]=OP_XOR;
            operands[ind][0]=a[i];
            operands[ind][1]=b[i];
            ind++;
            operations[ind]=OP_XOR;
            operands[ind][0]=ind-1;
            operands[ind][1]=carry;
            ans[i]=ind;
            ind++;

            //set carry for next bit
            operations[ind]=OP_AND;
            operands[ind][0]=a[i];
            operands[ind][1]=b[i];
            int ab = ind;
            ind++;
            operations[ind]=OP_AND;
            operands[ind][0]=carry;
            operands[ind][1]=b[i];
            int bc = ind;
            ind++;
            operations[ind]=OP_AND;
            operands[ind][0]=a[i];
            operands[ind][1]=carry;
            int ac = ind;
            ind++;
            //xor these 3
            operations[ind]=OP_XOR;
            operands[ind][0]=ab;
            operands[ind][1]=ac;
            ind++;
            operations[ind]=OP_XOR;
            operands[ind][0]=ind-1;
            operands[ind][1]=bc;
            carry=ind;
            ind++;
        }
        return ans;
    };

    vector<vector<int>>buckets[n];

    for(int i = 0;i<m;i++){
        //first find what persons number is being transferred for this message
        vector<int>inds(n);
        for(int s = 0;s<n;s++){
            inds[s]=checkEqual(people[s],msgs[i][0]);
        }
        ///one of inds is 1 that persons number is being transferred rn
        ///multiple all number by respective bit and then or all the results
        vector<int>curnums[n];
        for(int s = 0;s<n;s++){
            curnums[s]=mult1(nums[s],inds[s]);
        }
        ///now or all nums here and put in one place
        vector<int>ord = curnums[0];
        for(int s = 1;s<n;s++){
            ord=orsum(ord,curnums[s]);
        }
        //ord is the current number that is being given to recipent
        //now find which person is receiving
        for(int s = 0;s<n;s++){
            inds[s]=checkEqual(people[s],msgs[i][1]);
        }
        //inds now stores which person has received it
        //multiple ord by inds for each of n and put the number in bucket of nth
        for(int e = 0;e<n;e++){
            buckets[e].push_back(mult1(ord,inds[e]));
        }
    }
    ///now each of buckets need to be added simply.
    for(int i = 0;i<n;i++){
        vector<int>curans = buckets[i][0];
        for(int j = 1;j<buckets[i].size();j++){
            curans=add(curans,buckets[i][j]);
        }
        for(int j = 0;j<numSize;j++){
            outputs_circuit[i][j]=curans[j];
        }
    }
    return ind;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...