#ifndef SRC_HPP #define SRC_HPP #include #include #include #include #include // 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 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 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