1091 資料結構

題目說明

計算各別病患與各疾病(ICD)的住院總天數。
健保資料庫住院檔記錄著病患的 ID 代碼、生日、性別、住院日期、出院日期、ICD 等等。所謂 ICD 即是國際疾病傷害及死因分類標準,是世界衛生組織依據疾病的某些特徵,依照規則將疾病分門別類,並用編碼的方法來表示的系統。在做某類疾病患者的住院天數分析時,可利用住院檔的資料進行統計。測資為模擬住院檔的格式,請計算出每個病患的所有診斷疾病(ICD)的總住院天數。

特別狀況:跨越、交錯、包含於
注意:住院日期可能會有跨月、交錯、包含的可能性。

  1. 正常的一筆紀錄
    A,20200401,20200415 (此例為 15 天)

  2. 跨月
    B,20200501,20200630 (此例為 61 天)

  3. 交錯
    C,20200601,20200630
    C,20200615,20200715 (此例為 45 天)

  4. 包含於
    D,20200801,20200831
    D,20200810,20200820 (此例為 31 天)

Input

輸入資料檔案欄位依序為「病患 ID、住院日期、出院日期、ICD_1、ICD_2、ICD_3」。病患 ID 為字串,住院和出院日期格式為「YYYYMMDD」,ICD_1、ICD_2、ICD_3 為三項當次住院醫生診斷的 ICD 碼。
下方範例中,
ID為ah18n4sj1g7r病人從20070501入住醫院並於20070515出院,並且ICD碼只有V440一項,此紀錄住院天數為15日。
ID為ah18n4sj1g7r病人從20070516入住醫院並於20070518出院,並且ICD碼為V440與25000兩項,此紀錄住院天數為3日。
ID為b2bf3ca6546d病人從20081213入住醫院並於20090105出院,並且ICD碼為1889與V1052兩項,此紀錄住院天數為24日。

範例輸入

1
2
3
ah18n4sj1g7r,20070501,20070515,V440,,
ah18n4sj1g7r,20070516,20070518,V440,25000,
b2bf3ca6546d,20081213,20090105,1889,V1052,

Output

輸出格式依序為「病患 ID、ICD、總天數」,並且先後依照各病患 ID、ICD 來升冪排序輸出(以 string 判斷大小方式)。
日期格式:YYYYMMDD
ex:20200513、20201203
總天數計算: 計算頭尾天數
ex: 住院日期為 20200513 且出院日期為 20200516,則住院天數為 4 天。
ex: 住院日期為 20200101 且出院日期為 20200205,則住院天數為 36 天。
ICD 碼共有三項:ICD_1、ICD_2、ICD_3
ICD 碼可以為空值,但每筆紀錄一定會有一項 ICD 碼。
ex: A1,A2,B2
ex: A1,,
ex: B2,C3,A1
出院日期可能為空值,如遇到出院日期為空值時,則假設出院日期為當月最後一天。
ex:id,20200513,,A1,, 代表該病患入院日期為 20200513,出院日期為 20200531

範例輸出

1
2
3
4
ah18n4sj1g7r,25000,3
ah18n4sj1g7r,V440,18
b2bf3ca6546d,1889,24
b2bf3ca6546d,V1052,24

解題思路

使用link list 將每個病人和他的資料串連起來。

參考解法

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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

int month[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

class Datalist;

struct Datanode
{
string id;
string ICD;
int day;
Datanode* next;
friend class Datalist;
};

struct unsortedData
{
string ICD;
string id;
vector <string> in;
vector <string> out;
int day = 0;
};

class Datalist
{
public:
Datalist() :first(0) {};
void print();
void push_back(string& id, string& ICD, int& day);

private:
Datanode* first;
};

void Datalist::push_back(string& id, string& ICD, int& day)
{
Datanode* newNode = new Datanode{ id, ICD, day };

if (first == 0) {
first = newNode;
return;
}

Datanode* current = first;

while (current->next != 0)
{
current = current->next;
}
current->next = newNode;
}

void Datalist::print()
{
Datanode* current = first;

while (current != 0)
{
cout << current->id << "," << current->ICD << "," << current->day << endl;

current = current->next;
}
}

bool exist(string str1, string str2)
{
if (str1 != str2)
{
return false;
}
else
{
return true;
}

}

bool leapyear(int& year)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
return true;
}
else
{
return false;
}
}

void load(ifstream& fin, vector<unsortedData>& temp)
{
string line;
while (getline(fin, line))
{
vector <string> datas;
string str = ",";
string substring;
string::size_type start = 0, index;
index = line.find_first_of(str, start);

do
{
if (index != string::npos)
{
substring = line.substr(start, index - start);
datas.push_back(substring);
start = index + str.size();
index = line.find(str, start);

if (start == string::npos)
{
break;
}
}
} while (index != string::npos);

substring = line.substr(start);
datas.push_back(substring);

int year, month;

if (datas[2] == "")
{
year = atoi(datas[1].substr(0, 4).c_str());
month = atoi(datas[1].substr(4, 2).c_str());

datas[2] = datas[1];

if (month == 1 || month == 3 ||
month == 5 || month == 7 || month == 8
|| month == 10 || month == 12)
{
datas[2][6] = '3';
datas[2][7] = '1';
}
else if (month == 4 || month == 6 ||
month == 9 || month == 11)
{
datas[2][6] = '3';
datas[2][7] = '0';
}
else if (month == 2)
{
datas[2][6] = '2';

if (leapyear(year))
{
datas[2][7] = '9';
}
else
{
datas[2][7] = '8';
}
}
}

if (!datas[3].empty())
{
unsortedData temp1;
temp1.id = datas[0];
temp1.ICD = datas[3];
temp1.in.push_back(datas[1]);
temp1.out.push_back(datas[2]);
temp.push_back(temp1);
}
if (!datas[4].empty())
{
unsortedData temp2;
temp2.id = datas[0];
temp2.ICD = datas[4];
temp2.in.push_back(datas[1]);
temp2.out.push_back(datas[2]);
temp.push_back(temp2);
}
if (!datas[5].empty())
{
unsortedData temp3;
temp3.id = datas[0];
temp3.ICD = datas[5];
temp3.in.push_back(datas[1]);
temp3.out.push_back(datas[2]);
temp.push_back(temp3);
}
}
}

int countDays(unsortedData& temp)
{
int sum = 0;

for (int i = 0; i < temp.in.size(); i++)
{
int in_year = atoi(temp.in[i].substr(0, 4).c_str());
int in_month = atoi(temp.in[i].substr(4, 2).c_str());
int in_day = atoi(temp.in[i].substr(6, 2).c_str());
int out_year = atoi(temp.out[i].substr(0, 4).c_str());
int out_month = atoi(temp.out[i].substr(4, 2).c_str());
int out_day = atoi(temp.out[i].substr(6, 2).c_str());

if (in_year == out_year)
{
if (leapyear(in_year))
{
month[2] = 29;
}
else
{
month[2] = 28;
}

if (in_month == out_month)
{
sum += out_day - in_day + 1;
}
else
{
while (in_month != out_month)
{
out_day += month[in_month];
in_month++;
}
sum += out_day - in_day + 1;
}
}
else
{
if (leapyear(in_year))
{
month[2] = 29;
}
else
{
month[2] = 28;
}

int diff = 0;
diff = out_year - in_year;

int diff1 = 0;
diff1 = out_month + (12 * diff) - in_month;

for (int i = 1; i <= diff1; i++)
{
while (in_month > 12)
{
in_month -= 12;
++in_year;

if (leapyear(in_year))
{
month[2] = 29;
}
else
{
month[2] = 28;
}
}

out_day += month[in_month];
in_month++;
}
sum += out_day - in_day + 1;
}
}

return sum;
}

void tidy1(vector <unsortedData>& temp, vector <unsortedData>& data)
{
for (int i = 0; i < temp.size(); i++)
{
bool tidy = false;

for (int j = 0; j < data.size(); j++)
{
if (exist(temp[i].id, data[j].id) && exist(temp[i].ICD, data[j].ICD))
{
if ((data[j].out[0] >= temp[i].in[0]) && !tidy)
{
if ((temp[i].out[0] <= data[j].out[0]) && !tidy)
{
tidy = true;
}
else
{
tidy = true;
data[j].out[0] = temp[i].out[0];
}
}
}
}

if (!tidy)
{
data.push_back(temp[i]);
}
}
}

void tidy2(vector <unsortedData>& data, vector <unsortedData>& sorteddata)
{
for (int i = 0; i < data.size(); i++)
{
bool tidy = false;

for (int j = 0; j < sorteddata.size(); j++)
{
if (exist(data[i].id, sorteddata[j].id) && exist(data[i].ICD, sorteddata[j].ICD))
{
tidy = true;

sorteddata[j].in.push_back(data[i].in[0]);
sorteddata[j].out.push_back(data[i].out[0]);
}
}

if (!tidy)
{
sorteddata.push_back(data[i]);
}
}
}

int main(int argc, char* argv[])
{
vector<unsortedData> temp;
vector<unsortedData> data;
vector<unsortedData> sorteddata;

ifstream fin;

fin.open(argv[1]);
//fin.open("case.txt");

load(fin, temp);

for (int i = 0; i < temp.size(); i++)
{
for (int j = 0; j < i; j++)
{
if (temp[j].id == temp[i].id)
{
if (temp[j].ICD == temp[i].ICD)
{
if (temp[j].in[0] == temp[i].in[0])
{
if (temp[j].out[0] > temp[i].out[0])
{
unsortedData newone = temp[j];
temp[j] = temp[i];
temp[i] = newone;
}
}
else if (temp[j].in[0] > temp[i].in[0])
{
unsortedData newone = temp[j];
temp[j] = temp[i];
temp[i] = newone;
}
}
else if (temp[j].ICD > temp[i].ICD)
{
unsortedData newone = temp[j];
temp[j] = temp[i];
temp[i] = newone;
}
}
else if (temp[j].id > temp[i].id)
{
unsortedData newone = temp[j];
temp[j] = temp[i];
temp[i] = newone;
}
}
}

tidy1(temp, data);
tidy2(data, sorteddata);

for (int i = 0; i < sorteddata.size(); i++)
{
sorteddata[i].day = countDays(sorteddata[i]);
}

Datalist list;

for (int i = 0; i < sorteddata.size(); i++)
{
list.push_back(sorteddata[i].id, sorteddata[i].ICD, sorteddata[i].day);
}

list.print();
}