aboutsummaryrefslogtreecommitdiff
path: root/challenge-094/paulo-custodio/cpp/ch-2.cpp
blob: 51be06b3385dda6577e0e7b6de9be1cca4eec168 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
Challenge 094

TASK #2 � Binary Tree to Linked List
Submitted by: Mohammad S Anwar
You are given a binary tree.

Write a script to represent the given binary tree as an object and flatten
it to a linked list object. Finally print the linked list object.

Example:
    Input:

        1
       / \
      2   3
     / \
    4   5
       / \
      6   7

    Output:

        1 -> 2 -> 4 -> 5 -> 6 -> 7 -> 3
*/

#include <exception>
#include <stdexcept>
#include <iostream>
#include <string>
#include <vector>
#include <cctype>

// input image object
class InputImage {
public:
    void append_line(const std::string& line);
    void clear();
    char ch(int row, int col) const;
    int root_col() const;

private:
    std::vector<std::string> m_lines;
};

void InputImage::append_line(const std::string& line) {
    m_lines.push_back(line);
}

void InputImage::clear() {
    m_lines.clear();
}

char InputImage::ch(int row, int col) const {
    // check if out of bounds
    if (row < 0 || row >= static_cast<int>(m_lines.size()) ||
        col < 0 || col >= static_cast<int>(m_lines[row].size()))
        return ' ';
    else
        return m_lines[row][col];
}

int InputImage::root_col() const {
    if (m_lines.empty())
        throw std::invalid_argument("malformed image");
    for (int col = 0; col < static_cast<int>(m_lines[0].size()); col++) {
        if (isdigit(m_lines[0][col]))
            return col;
    }
    throw std::invalid_argument("malformed image");
}

// tree object
class Tree {
public:
    Tree(int value = 0);
    ~Tree();

    int value;
    Tree* left, * right;

    static Tree* parse(const InputImage& image);
    static Tree* flatten(Tree* root);

private:
    static Tree* parse_subtree(const InputImage& image, int row, int col);
};

Tree::Tree(int value_)
    : value(value_), left(nullptr), right(nullptr)
{}

Tree::~Tree() {
    if (left) delete left;
    if (right) delete right;
}

Tree* Tree::parse(const InputImage& image) {
    int col = image.root_col();
    return parse_subtree(image, 0, col);
}

Tree* Tree::parse_subtree(const InputImage& image, int row, int col) {
    // parse root
    int value = image.ch(row, col) - '0';
    if (value < 0 || value>9)
        throw std::invalid_argument("malformed image");
    Tree* node = new Tree(value);

    // parse left subtree
    if (image.ch(row + 1, col - 1) == '/')
        node->left = parse_subtree(image, row + 2, col - 2);
    // parse right subtree
    if (image.ch(row + 1, col + 1) == '\\')
        node->right = parse_subtree(image, row + 2, col + 2);

    return node;
}

Tree* Tree::flatten(Tree* root) {
    if (!root) return root;
    Tree* left = flatten(root->left);
    Tree* right = flatten(root->right);

    root->left = NULL;
    root->right = left;

    Tree* node = root;
    while (node->right)             // find right-most node
        node = node->right;
    node->right = right;

    return root;
}

// read input from stdin
void read_lines(InputImage& image) {
    image.clear();
    std::string line;
    while (!std::getline(std::cin, line).eof())
        image.append_line(line);
}

int main(int argc, char* argv[]) {
    InputImage image;
    read_lines(image);
    Tree* tree = Tree::flatten(Tree::parse(image));

    for (Tree* node = tree; node; node = node->right) {
        if (node != tree)
            std::cout << " -> ";
        std::cout << node->value;
    }
    std::cout << std::endl;
    delete tree;
}