#include <iostream>
#include <string>
using namespace std;

template <class ITEMTYPE>
class Node {

public:

	ITEMTYPE cargo;
	Node<ITEMTYPE>* next;

	Node () {
		cargo = ITEMTYPE();
		next = NULL;
	}

	Node (ITEMTYPE Cargo, Node<ITEMTYPE>* Next) {
		cargo = Cargo;
		next = Next;
	}

};
/*
template<class ITEMTYPE>
void printList (Node<ITEMTYPE>* list) {
	Node<ITEMTYPE>* node = list;

	while (node != NULL) {
		cout << node->cargo;
		node = node->next;
	}
	cout << endl;
}
 */

template <class ITEMTYPE>
void printList(Node<ITEMTYPE>* list) {
    for (Node<ITEMTYPE>* node = list; node != NULL; node = node->next) {
        cout << node->cargo;
    }
}

template <class ITEMTYPE>
void prettyPrint (Node<ITEMTYPE>* list) {
    cout << '(';
    // print out elements
    Node<ITEMTYPE>* node = list;
    while (node != NULL) {
        cout << node->cargo;
        if (node->next != NULL) cout << ", ";
        node = node->next;
    }
    cout << ')';
}

template <class ITEMTYPE>
void printBackward (Node<ITEMTYPE>* list) {
    if (list == NULL) return;

    Node<ITEMTYPE>* head = list;
    Node<ITEMTYPE>* tail = list->next;

    printBackward (tail);
    cout << head->cargo;
}

template <class ITEMTYPE>
void printBackwardNicely (Node<ITEMTYPE>* list) {
    cout << '(';
    if (list != NULL) {
        printBackward (list);
    }
    cout << ')';
}


template <class ITEMTYPE>
Node<ITEMTYPE>* removeSecond (Node<ITEMTYPE>* list) {
	Node<ITEMTYPE>* first = list;
	Node<ITEMTYPE>* second = list->next;

	// make the first node refer to the third
	first->next = second->next;

	// separate the second node from the rest of the list
	second->next = NULL;
	return second;
}

template <class ITEMTYPE>
class LinkedList {

public:
    int length;
    Node<ITEMTYPE>* head;

    LinkedList () {
        length = 0;
        head = NULL;
    }

    void printBackwardNicely () {
        cout << '(';

        if (head != NULL) {
            Node<ITEMTYPE>* tail = head->next;
            printBackward (tail);
            cout << head->cargo;
        }
        cout << ')';
    }

	void addFirst (ITEMTYPE i) {
		Node<ITEMTYPE>* node = new Node<ITEMTYPE> (i, head);
		head = node;
		length++;
    }

};


int main () {
    Node<int> node = Node<int> (1, NULL);
    cout << node.cargo << endl;

	Node<int>* pnode = new Node<int> (2, NULL);
    cout << (*pnode).cargo << endl;
    cout << pnode->cargo << endl;

	Node<int>* pnode1 = new Node<int> (1, NULL);
    Node<int>* pnode2 = new Node<int> (2, NULL);
    Node<int>* pnode3 = new Node<int> (3, NULL);

	cout << pnode1->cargo << pnode2->cargo << pnode3->cargo << endl;

    // (*pnode1).next = pnode2;
	pnode1->next = pnode2;
    pnode2->next = pnode3;
    pnode3->next = NULL;

	printList (pnode1); cout << endl;
    prettyPrint(pnode1); cout << endl;

	printBackward (pnode1); cout << endl;

    printBackwardNicely (pnode1); cout << endl;

	prettyPrint (pnode1); cout << endl;
	Node<int>* removed = removeSecond (pnode1);
	prettyPrint (removed); cout << endl;
	prettyPrint (pnode1);  cout << endl;


	LinkedList<int> L;
	L.addFirst(7);
	L.addFirst(8);
	L.addFirst(9);
	L.printBackwardNicely(); cout << endl;

	LinkedList<string> SL;
	SL.addFirst("first");
	SL.addFirst("second");
	SL.printBackwardNicely(); cout << endl;

    LinkedList<int> M;
    int x;
    cin >> x;
    while (x >= 0) {
        M.addFirst(x);
        cin >> x;
    }
    M.printBackwardNicely(); cout << endl;

	cout << endl;

	return 0;
}


