#include <iostream>
#include <string>
#include <vector>        //动态数组
#include <list>
#include <algorithm>
#include <cctype>

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::max;


vector<string> split(const string& s) {        //分割字符串，按空格分割成单词，并存储在vector<string>中
    vector<string> ret;
    typedef string::size_type string_size;
    string_size  i = 0;

    while (i != s.size()) {
        //忽略前段的空白：[先前的i,i)中全部字符都是空格
        while (i != s.size() && isspace(s[i])) {
            i++;
        }
        //找出下一个单词的终结点
        string_size j = i;
        //[先前的j,j)中的任意字符都不是空格
        while (j != s.size() && !isspace(s[j])) {
            j++;
        }
        //找到了一些非空白符
        if (i != j) {
            ret.push_back(s.substr(i, j - i));
            i = j;
        }
    }
    return ret;
}


//找出向量中最长字符串的长度
string::size_type width(const vector<string>& v) {   //计算字符串向量中最长字符串的长度
    string::size_type  maxlen = 0;
    for (vector<string>::size_type i = 0; i != v.size(); ++i) {
        maxlen = max(maxlen, v[i].size());
    }
    return maxlen;
}

vector<string> frame(const vector<string>& v) {
    vector<string> ret;
    string::size_type maxlen = width(v);    //计算每行最长字符串长度
    //输出顶部边框
    string border(maxlen + 4, '*');

    //输出内部的行，每行都用一个星号和一个空格来框起来
    ret.push_back(border);
    //使用迭代器实现
    vector<string>::const_iterator iter = v.begin();
    while (iter != v.end()) {    //每行输出中间的字符串，两边填充空格，使其宽度一致
        ret.push_back("* " + (*iter) + string(maxlen - iter->size(), ' ') + " *");
        iter++;
    }
    ret.push_back(border);
    return  ret;
}

//纵向连接
vector<string> vcat(const vector<string>& top, const vector<string>& bottom) {
    vector<string> ret = top;
    ret.insert(ret.end(), bottom.begin(), bottom.end());
    return  ret;
}

//横向连接
vector<string> hcat(const vector<string>& left, const vector<string>& right) {
    vector<string>ret;
    //在两幅图案之间留空格
    string::size_type width1 = width(left) + 1;
    //用于遍历left和right的索引
    //使用迭代器
    vector<string>::const_iterator i, j;
    i = left.begin();
    j = right.begin();
    while (i != left.end() || j != right.end()) {
        string s;
        if (i != left.end()) {
            s = *i++;
        }

        s += string(width1 - s.size(), ' ');

        if (j != right.end()) {
            s += *j++;
        }
        ret.push_back(s);
    }

    return  ret;
}

int main(int argc, const char* argv[]) {
    string s;
    while (getline(cin, s)) {
        vector<string> v = split(s);
        vector<string> fra = frame(v);  //调用frame对分割后的单词添加框架
        vector<string> col, row;
        col = vcat(v, fra);  
        row = hcat(v, fra);  //通过hcat将分割文本和框架化文本并排显示并输出到屏幕上
        for (vector<string>::size_type j = 0; j != row.size(); ++j) {
            cout << row[j] << endl;
        }
    }
    return 0;
}


#include <iostream>     // 引入标准输入输出流库
#include <string>       // 引入字符串库
#include <vector>       // 引入动态数组（vector）容器库
#include <list>         // 引入链表容器库（未使用）
#include <algorithm>    // 引入算法库（用于std::max）
#include <cctype>       // 引入字符处理函数库（用于std::isspace）

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::max;

// 按空格分割字符串，返回分割后的单词向量
vector<string> split(const string& s) {
    vector<string> ret;                      // 存储分割结果
    typedef string::size_type string_size;   // 定义字符串长度的类型
    string_size i = 0;

    while (i != s.size()) {
        // 跳过空格
        while (i != s.size() && isspace(s[i])) {
            i++;
        }

        // 找到下一个单词的结束位置
        string_size j = i;
        while (j != s.size() && !isspace(s[j])) {
            j++;
        }

        // 如果找到单词，将其添加到结果中
        if (i != j) {
            ret.push_back(s.substr(i, j - i)); // 提取单词并存入向量
            i = j; // 更新索引位置
        }
    }
    return ret;
}

// 找出向量中最长字符串的长度
string::size_type width(const vector<string>& v) {
    string::size_type maxlen = 0; // 初始化最大长度为0
    for (vector<string>::size_type i = 0; i != v.size(); ++i) {
        maxlen = max(maxlen, v[i].size()); // 更新最大长度
    }
    return maxlen;
}

// 为向量中的字符串添加框架（边框）
vector<string> frame(const vector<string>& v) {
    vector<string> ret;                      // 存储框架化后的字符串
    string::size_type maxlen = width(v);     // 计算最长字符串长度
    string border(maxlen + 4, '*');          // 定义边框字符串

    ret.push_back(border);                   // 添加顶部边框
    vector<string>::const_iterator iter = v.begin();

    while (iter != v.end()) {
        // 每行添加左右边框和适当的填充
        ret.push_back("* " + (*iter) + string(maxlen - iter->size(), ' ') + " *");
        iter++;
    }
    ret.push_back(border);                   // 添加底部边框
    return ret;
}

// 纵向连接两个字符串向量
vector<string> vcat(const vector<string>& top, const vector<string>& bottom) {
    vector<string> ret = top;                // 初始化结果为顶部向量
    ret.insert(ret.end(), bottom.begin(), bottom.end()); // 添加底部向量
    return ret;
}

// 横向连接两个字符串向量
vector<string> hcat(const vector<string>& left, const vector<string>& right) {
    vector<string> ret;
    string::size_type width1 = width(left) + 1; // 为左侧添加一个空格的宽度
    vector<string>::const_iterator i = left.begin(), j = right.begin();

    // 同时遍历左、右向量
    while (i != left.end() || j != right.end()) {
        string s;

        if (i != left.end()) {
            s = *i++; // 获取左侧字符串
        }

        s += string(width1 - s.size(), ' '); // 填充空格以对齐

        if (j != right.end()) {
            s += *j++; // 添加右侧字符串
        }

        ret.push_back(s); // 将拼接后的字符串添加到结果
    }

    return ret;
}

int main(int argc, const char* argv[]) {
    string s;
    while (getline(cin, s)) {
        // 按空格分割输入字符串
        vector<string> v = split(s);
        // 为分割后的字符串添加框架
        vector<string> fra = frame(v);
        // 纵向连接原始字符串和框架化字符串
        vector<string> col = vcat(v, fra);
        // 横向连接原始字符串和框架化字符串
        vector<string> row = hcat(v, fra);

        // 输出横向连接后的结果
        for (vector<string>::size_type j = 0; j != row.size(); ++j) {
            cout << row[j] << endl;
        }
    }
    return 0;
}
