/*
Subject: #159 - Word Crosses
e-mail: morcavon@gmail.com
Homepage: http://www.morcavon.com
Building: 06/07/2005 ~ 07/07/2005
Last Update: 07/07/2005
*/
/*
<PURPOSE>
Write a program that will read in sets of four words and
form them(if possible) into double leading word crosses.
-
<PREDICATE>
1 <= length of word <= 10
-
<INPUT>
word1 word2 word3 word4 word1,2: hor / word3,4: vert
...
#
-
<OUTPUT>
double leading word crosses.(three spaces between the horizontal words)
blacnk
....
"Unable to make two crosses"(not possible to from both crosses)
*/
#include <iostream>
using namespace std;
#include <cstring>
#define ONLINE_JUDGE
int cross(char word1[], char word2[], short *h, short *v);
int main()
{
char worda[11], wordb[11], wordx[11], wordy[11];
// 교차점의 인덱스
// v1,v2는 각 크로스에서 교차점 위로 올라간 문자의 개수를 나타냄
// (이 값이 큰 크로스의 높이에 맞춰 출력)
short h1, v1, h2, v2;
short k;
short len1, len2, len4; // 단어의 길이
short upperboud; // 두 크로스의 전체적인 상위 경계(0부터 시작해서)
short horz; // 두 워드를 출력할 위치
short left[2], right[2]; // 좌우 크로스의 상하바운드([0]:상, [1]:하)
bool endflag = true;
while (cin >> worda) {
if (worda[0] == '#')
break;
cin >> wordb >> wordx >> wordy;
if (endflag == false) // 첫 출력시에만 한칸을 띄우지 않음.
cout << "\n\n";
endflag = false;
if (cross(worda, wordb, &h1, &v1) && cross(wordx, wordy, &h2, &v2)) {
// double leading word crosses를 구성 할 수 있음...
len1 = strlen(worda);
len2 = strlen(wordb);
len4 = strlen(wordy);
upperboud = ((v1 > v2)? v1 : v2) +
((len2 - v1 - 1 > len4 - v2 - 1)? len2 - v1 - 1: len4 - v2 - 1);
horz = upperboud - ((v1 > v2)? v1 : v2);
left[0] = horz + v1;
left[1] = horz - (len2 - v1) + 1;
right[0] = horz + v2;
right[1] = horz - (len4 - v2) + 1;
#ifndef ONLINE_JUDGE
cout << "h1 = " << h1 << ", v1 = " << v1 << ", h2 = " << h2 << ", v2 = " << v2;
cout << "\nlen1 = " << len1 << ", len2 = " << len2 << ", len4 = " << len4 << '\n';
cout << "upper = " << upperboud << '\n';
#endif
for (k = upperboud; k >= 0; k--) { // 0 ~ upperbound
// 아래로 내려가면서 먼저 왼쪽 크로스 부분을 출력하고 오른쪽 크로스 출력
if (k == horz) { // 두 워드를 출력
cout << worda << " " << wordx;
}
else {
if (k <= left[0] && k >= left[1]) { // 왼쪽 크로스 출력
cout.width(h1+1);
cout << wordb[left[0] - k];
if (k <= right[0] && k >= right[1]) { // 양쪽 크로스에 다 출력되는 경우
// 왼쪽에 이미 출력된 만큼 빼고 여백을 줌
cout.width(len1 - (h1 + 1) + 3 + h2 + 1);
cout << wordy[right[0] - k];
}
}
else { // 왼쪽은 출력하지 않고 오른쪽만 출력하는 경우
cout.width(len1 + 3 + h2 + 1);
cout << wordy[right[0] - k];
}
}
if (k != 0)
cout << '\n';
} // end of for()
}
else
cout << "Unable to make two crosses";
}
return 0;
}
int cross(char word1[], char word2[], short *h, short *v)
{
// word1과 word2가 크로스를 이루는지 확인하여 겹치는 단어의 인덱스를 저장, 실패시 0 리턴
short i, j;
for (i = 0; word1[i] != '\0'; i++) {
for (j = 0; word2[j] != '\0'; j++) {
if (word1[i] == word2[j]) { // 제일 처음 나타나는 문자를 찾는다
*h = i;
*v = j;
return 1;
}
}
}
return 0;
}