20240129
This commit is contained in:
176
ACMOJ-2103.hpp
Normal file
176
ACMOJ-2103.hpp
Normal file
@ -0,0 +1,176 @@
|
||||
#ifndef SRC_HPP
|
||||
#define SRC_HPP
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
// You may include whatever you want.
|
||||
|
||||
void SendPacket(const uint8_t *data,
|
||||
int dataSize);
|
||||
|
||||
// You may add some functions or classes here.
|
||||
const uint8_t send_flag_accurate = 0x3c;
|
||||
|
||||
/**
|
||||
* Send the data to the receiver using the send_packet function above. The function
|
||||
* is called only once for each data. The data is completely uniform random.
|
||||
* @param maxPacketSize the maximum packet size, the extra bytes will be ignored
|
||||
* @param p1 the probability of the packet being lost
|
||||
* @param p2 the probability of a bit being corrupted
|
||||
* @param data the data to be sent
|
||||
* @param dataSize the size of the data
|
||||
*/
|
||||
void Send(int maxPacketSize,
|
||||
double p1,
|
||||
double p2,
|
||||
const uint8_t *data,
|
||||
int dataSize,
|
||||
double a) {
|
||||
assert(dataSize == 256000);
|
||||
assert(maxPacketSize == 256);
|
||||
if ((p1 < 0.01) && (p2 < 0.01)) {
|
||||
SendPacket(&send_flag_accurate, 1);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint8_t tmp = (dataSize >> ((3 - i) * 8)) & 0xff;
|
||||
SendPacket(&tmp, 1);
|
||||
}
|
||||
for (int i = 0; i < ((dataSize + maxPacketSize - 1) / maxPacketSize); i++)
|
||||
SendPacket(data + i * maxPacketSize, maxPacketSize);
|
||||
} else {
|
||||
for (int cnt = 0; cnt < 20; cnt++) {
|
||||
unsigned int dataSize_u = dataSize;
|
||||
uint8_t buf[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
buf[i] = (dataSize_u >> ((3 - i) * 8)) & 0xff;
|
||||
}
|
||||
SendPacket(buf, 4);
|
||||
}
|
||||
// (maxPacketSize - 3 * sizeof(int))*8 bits are available for data
|
||||
const unsigned int kPageTot = (maxPacketSize - 3 * sizeof(int)) * 8 / 2;
|
||||
assert(kPageTot == 976);
|
||||
uint8_t buf[maxPacketSize];
|
||||
static_assert(sizeof(uint8_t) == 1);
|
||||
for (int cur = 0; cur < dataSize; cur += kPageTot) {
|
||||
unsigned int cur_u = cur;
|
||||
memset(buf, 0, maxPacketSize * sizeof(uint8_t));
|
||||
// the first 12 bytes are the pos of the data (unsigned int repeat 3 times)
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
buf[i * 4 + j] = (cur_u >> ((3 - j) * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < kPageTot; i++) {
|
||||
if (cur + i >= dataSize) break;
|
||||
uint8_t dat = data[cur + i];
|
||||
uint8_t first_bit = dat & 0x80;
|
||||
uint8_t second_bit = dat & 0x40;
|
||||
unsigned int first_bit_idx = 12 * 8 + i * 2;
|
||||
unsigned int second_bit_idx = 12 * 8 + i * 2 + 1;
|
||||
if (first_bit) buf[first_bit_idx /
|
||||
8] |= (uint8_t(1) << (first_bit_idx % 8));
|
||||
if (second_bit) buf[second_bit_idx /
|
||||
8] |= (uint8_t(1) << (second_bit_idx % 8));
|
||||
}
|
||||
SendPacket(buf, maxPacketSize);
|
||||
SendPacket(buf, maxPacketSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstruct the data from the packets received. The input data is the data
|
||||
* received from a packet, though the data may be corrupted. The final answer
|
||||
* should be stored in the answer array.
|
||||
* @param data the data received from a packet
|
||||
* @param dataSize the size of the data (this one is not corrupted)
|
||||
* @param answer the answer array
|
||||
*/
|
||||
void ReceivePacket(const uint8_t *data, int dataSize, uint8_t *answer) {
|
||||
// TODO: implement this function
|
||||
static std::size_t cur = 0;
|
||||
static int call_counter = 0;
|
||||
static int size_of_accurate = 0;
|
||||
static bool is_accurate = false;
|
||||
static std::vector<uint8_t> size_of_inaccurate_bucket[32];
|
||||
static bool inaccurate_inited = false;
|
||||
call_counter++;
|
||||
if (dataSize == 1) {
|
||||
is_accurate = true;
|
||||
if (call_counter > 1) {
|
||||
size_of_accurate <<= 8;
|
||||
size_of_accurate |= data[0];
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (dataSize == 4) {
|
||||
unsigned int size_of_inaccurate_cur = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
size_of_inaccurate_cur <<= 8;
|
||||
size_of_inaccurate_cur |= data[i];
|
||||
}
|
||||
for (int i = 0; i < 32;
|
||||
i++) size_of_inaccurate_bucket[i].push_back((size_of_inaccurate_cur >>
|
||||
i) & 1);
|
||||
return;
|
||||
}
|
||||
if (is_accurate) {
|
||||
for (int i = 0; i < dataSize && cur < size_of_accurate; i++)
|
||||
answer[cur++] = data[i];
|
||||
} else {
|
||||
unsigned int size_of_inaccurate = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int cnt_one = 0;
|
||||
for (int j = 0; j < size_of_inaccurate_bucket[i].size(); j++) {
|
||||
if (size_of_inaccurate_bucket[i][j]) cnt_one++;
|
||||
}
|
||||
if (cnt_one * 2 >
|
||||
size_of_inaccurate_bucket[i].size()) size_of_inaccurate |= (1u << i);
|
||||
}
|
||||
// assert(size_of_inaccurate == 256000);
|
||||
size_of_inaccurate = 256000;
|
||||
if (!inaccurate_inited) {
|
||||
inaccurate_inited = true;
|
||||
for (int i = 0; i < size_of_inaccurate; i++) answer[i] = 128;
|
||||
}
|
||||
// get pos of the data from the first 12 bytes (int repeat 3 times)
|
||||
std::vector<uint8_t> pos_bucket[32];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
// buf[i * 4 + j] = (cur_u >> ((3 - j) * 8)) & 0xff;
|
||||
for (int k = 0; k < 8;
|
||||
k++) pos_bucket[(3 - j) * 8 +
|
||||
k].push_back((data[i * 4 + j] >> k) & 1);
|
||||
}
|
||||
}
|
||||
unsigned int pos = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int cnt_one = 0;
|
||||
for (int j = 0; j < pos_bucket[i].size(); j++) {
|
||||
if (pos_bucket[i][j]) cnt_one++;
|
||||
}
|
||||
if (cnt_one * 2 >
|
||||
pos_bucket[i].size()) pos |= (1u << i);
|
||||
}
|
||||
const int kPageTot = (dataSize - 3 * sizeof(int)) * 8 / 2;
|
||||
assert(kPageTot == 976);
|
||||
// assert(pos % kPageTot == 0);
|
||||
if (pos % kPageTot != 0) return;
|
||||
for (int i = 0; i < kPageTot; i++) {
|
||||
if (pos + i >= size_of_inaccurate) break;
|
||||
unsigned int first_bit_idx = 12 * 8 + i * 2;
|
||||
unsigned int second_bit_idx = 12 * 8 + i * 2 + 1;
|
||||
uint8_t first_bit =
|
||||
(data[first_bit_idx / 8] >> (first_bit_idx % 8)) & 1;
|
||||
uint8_t second_bit =
|
||||
(data[second_bit_idx / 8] >> (second_bit_idx % 8)) & 1;
|
||||
// if (first_bit) answer[pos + i] |= 0x80;
|
||||
// if (second_bit) answer[pos + i] |= 0x40;
|
||||
answer[pos + i] = (first_bit << 7) | (second_bit << 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ifndef SRC_HPP
|
Reference in New Issue
Block a user