// Oldham, Jeffrey D. // 2000 Jan 16 // CS1321 // Unary Natural Numbers Implemented Using Lists (Incomplete) // Revisions: // 2000Jan24 Removed size_type from addOneToVector(). It is probably // implemented as an integer. Call in operator<<() also changed. #include "seq.h" #include #include // has isdigit() #include // used for output conversion #include #include // The Basic Definitions // Let's use the name "natural" for our numbers. It is easier to type // than "Seq". typedef Seq natural; // the simplest number const natural zero = Seq(); // The constructor add1() constructs a larger number. natural add1(const natural & n) { // WRITE THIS FUNCTION. } // If given a number larger than zero, sub1() is the selector. natural sub1(const natural & n) { // WRITE THIS FUNCTION. } // The predicate iszero() yields true if the number is zero, not a // larger number. bool iszero(const natural & n) { // WRITE THIS FUNCTION. } // Relational Operators // DEFINE THESE FUNCTIONS. // Arithmetic operations. natural operator+(const natural & m, const natural & n) { // WRITE THIS FUNCTION. } natural operator*(const natural & m, const natural & n) { // WRITE THIS FUNCTION. } // DEFINE THE REST OF THE FUNCTIONS. // Input and Output Routines // ten is the base for our notation. const natural ten = add1(add1(add1(add1(add1(add1(add1(add1(add1(add1(zero)))))))))); // Convert a base-10 number to unary. natural convertSingleDigit(const char c) { assert(isdigit(c)); // sanity check if (c == '0') return zero; else return add1(convertSingleDigit(c-1)); } natural convertAnotherDigit(const natural & answerSoFar, const char c) { return answerSoFar * ten + convertSingleDigit(c); } // JDO: 2000Jan26 This code did not correctly detect end of file. // istream& operator>>(istream& in, natural& input) { // input = zero; // in >> ws; // while (isdigit(in.peek())) // input = convertAnotherDigit(input,in.get()); // return in; // } istream& operator>>(istream& in, natural& input) { natural temp = zero; in >> ws; char c; bool foundone = false; while (in.get(c)) { if (isdigit(c)) { temp = convertAnotherDigit(temp,c); foundone = true; } else { // non-digit input in.putback(c); if (foundone) input = temp; else in.setstate(std::ios::failbit); return in; } } if (in.eof() && foundone) { // number ends the input input = temp; in.clear(std::ios::eofbit); return in; } else // EOF or input corrupted return in; } // Convert a unary number to base-10. // We will use a helper vector of the digits in reverse order. For // example, the number 750 will be represented as 057. template vector addOneToVector(vector &v, ForwardIterator position) { if (*position < '9') { ++(*position); return v; } else { // must carry *position = '0'; if (++position == v.end()) { // grow number by one digit v.push_back('1'); return v; } else return addOneToVector(v,position); } } // JDO 2000Jan24: size_type is probably implemented as an integer // vector addOneToVector(vector &v, const vector::size_type index) { // if (v[index] < '9') { // ++v[index]; // return v; // } // else { // must carry // v[index] = '0'; // if (index + 1 == v.size()) { // grow number by one digit // v.push_back('1'); // return v; // } // else // return addOneToVector(v,index+1); // } // } ostream& reverseVector(vector & v, ostream& out) { if (v.size() == 0) return out; else { out << v.back(); v.pop_back(); return reverseVector(v, out); } } inline ostream& operator<<(ostream& out, natural n) { vector v; v.push_back('0'); while (!iszero(n)) { // JDO 2000Jan24 v = addOneToVector(v, 0); v = addOneToVector(v, v.begin()); n = sub1(n); } return reverseVector(v, out); }