#include #include #include #include #include using namespace std; // first is number of bytes used, second is index into data that is next struct state { state() { current = ""; nextInd = 0; } string current; int nextInd; int prev; }; const int INVALID = -100; // Things that are "LARGER" come out of the priority queue first, // so we want to give preference to small strings. bool operator < (const state& rhs, const state& lhs) { if (rhs.current.size() < lhs.current.size()) return false; if (rhs.current.size() > lhs.current.size()) return true; if (rhs.nextInd > lhs.nextInd) return false; if (rhs.nextInd < lhs.nextInd) return true; if (rhs.prev > lhs.prev) return false; if (rhs.prev < lhs.prev) return true; return false; } // Can we make a valid frame out of the given data range with // the given starting value? bool validFrame(vector& data, int start, int end, int cur) { if (cur == INVALID) return false; for (int i = start; i <= end; i++) { int diff = cur - data[i]; if (diff < -16 or diff > 15) return false; cur = data[i]; } // You can make a frame out of this return true; } // Can we make a valid frame out of the given data range? bool validFrame(vector& data, int start, int end) { return validFrame(data, start + 1, end, data[start]); } // Convert c into the appropriate number of bits (2's complement style) string signedbits(int c, int bits) { string ret = ""; int mask = 1 << (bits - 2); if (c < 0) { ret += "1"; c += (1 << (bits - 1)); } else { ret += "0"; } for (int i = 0; i < bits - 1; i++) { if (c & mask) ret += "1"; else ret += "0"; mask >>= 1; } return ret; } // Convert c into the appropriate number of bits, unsigned string unsignedbits(int c, int bits) { string ret = ""; int mask = 1 << (bits - 1); for (int i = 0; i < bits; i++) { if (c & mask) ret += "1"; else ret += "0"; mask >>= 1; } return ret; } // How many bits would it take to encode the given deltas? // (This should only be called after validFrame has validated the range) pair calcDeltaSize(vector& data, int start, int end, int cur) { int ret = 2; for (int i = start; i <= end; i++) { if (i == data.size()) break; int diff = data[i] - cur; int temp; if (diff > 7) temp = 5; else if (diff > 3) temp = 4; else if (diff > 1) temp = 3; else if (diff >= -2) temp = 2; else if (diff >= -4) temp = 3; else if (diff >= -8) temp = 4; else temp = 5; ret = max(ret, temp); cur = data[i]; } if (ret == 2) return pair(2, "00"); if (ret == 3) return pair(3, "01"); if (ret == 4) return pair(4, "10"); return pair(5, "11"); } // Generate a frame that uses "cur" as the previous value and // only has deltas in it string genFrame(vector& data, int start, int end, int cur) { pair t = calcDeltaSize(data, start + 1, end, cur); int deltaSize = t.first; string sDeltaSize = t.second; string ret = "10"; ret += sDeltaSize; ret += unsignedbits(end - start, 4); for (int i = start; i <= end; i++) { int diff = data[i] - cur; ret += signedbits(diff, deltaSize); cur = data[i]; } return ret; } // Generate a frame that has an absolute data value following // the header, and then deltas starting at that value. string genFrame(vector& data, int start, int end) { pair t = calcDeltaSize(data, start + 1, end, data[start]); int deltaSize = t.first; string sDeltaSize = t.second; string ret = "11"; ret += sDeltaSize; ret += unsignedbits(end - start, 4); ret += signedbits(data[start], 8); int cur = data[start]; for (int i = start + 1; i <= end; i++) { int diff = data[i] - cur; ret += signedbits(diff, deltaSize); cur = data[i]; } return ret; } // Do the BFS void process(vector data) { // Starting state: haven't converted anything state start; // Places we have been (shouldn't really be needed, but it speeds us // up a little bit). set visited; // And the places to visit. This is a priority queue so we can // focus on those strings that are shortest thanks to our < operator priority_queue toVisit; // Note that the first thing MUST be an absolute measurement start.prev = INVALID; // Note where we start toVisit.push(start); // And do the prioritized-search while (not toVisit.empty()) { // Get the next one state cur = toVisit.top(); toVisit.pop(); // Are we done? if (cur.nextInd == data.size() and (best == "" or best.size() > cur.current.size())) { // Print this plus the stop-bit cout << cur.current << 0 << endl; return; } // Calculate the upper bound on the number of measurements in // this frame. int upper = 16 + cur.nextInd; if (upper > data.size()) upper = data.size(); for (int i = cur.nextInd + 1; i <= upper; i++) { // Generate a new state by making a frame out of // values ind..ind+i. This might not be possible. If it is // and we haven't seen that state before, enqueue it if (validFrame(data, cur.nextInd, i)) { // Get the new frame added in to a new state string newFrame = genFrame(data, cur.nextInd, i); state newState = cur; newState.current += newFrame; newState.nextInd = i + 1; newState.prev = data[i]; // IF we haven't seen that state, try it out later if (not visited.count(newState)) { visited.insert(newState); toVisit.push(newState); } } // A new frame that has no 8-bit full value (only deltas) if (validFrame(data, cur.nextInd, i, cur.prev)) { // Get the new frame added to the state string newFrame = genFrame(data, cur.nextInd, i, cur.prev); // If we haven't seen that state, try it again later state newState = cur; newState.current += newFrame; newState.nextInd = i + 1; newState.prev = data[i]; if (not visited.count(newState)) { visited.count(newState); toVisit.push(newState); } } } } // Shouldn't get here, everything is solvable } int main() { int t; vector data; // Read data until there is no more while (cin >> t) { // Process on command if (t == -128) { process(data); data.resize(0); } else { data.push_back(t); } } }