THÔNG TIN VỀ CHẤT LƯỢNG KHÔNG KHÍ TẠI NEW YORK TỪ THÁNG 5 NĂM 1973
ĐẾN THÁNG 9 NĂM 1973
- Thông tin bộ dữ liệu
library(datasets)
data(package = 'datasets')
library(ggplot2)
data(package = 'ggplot2')
dq <- airquality
Đồ thị số 1
library(tidyverse)
library(scales)
dq <- airquality
dq %>% group_by(Wind) %>% summarise(n = n()) %>%
ggplot(aes(Wind,n)) +
geom_col(fill='skyblue') +
geom_text(aes(label = n),vjust = 2, color = 'red') +
labs(x = 'Tốc độ gió', y = 'Số lượng')

Ta Phân loại tốc độ gió theo từng mức độ và tính số lượng của
từng mức độ.
x là từng mức độ của tốc độ gió, y là số lượng của từng mức
.
Các số liệu có màu đỏ, được điều chỉnh ở vị trí dọc cách cột 2
đơn vị. Màu của các cột là màu xanh da trời.
Biểu đồ thể hiện sự phân bố số lượng theo từng mức tốc độ
gió.
Có một số mức tốc độ gió có số lượng cao hơn, cụ thể là:
Có một số mức tốc độ gió có số lượng thấp hơn, cụ thể là:
- Mức dưới 5 mph và trên 20 mph có số lượng thấp nhất.
Đồ thị số 2
dq <- airquality
dq <- dq %>% group_by(Month, Ozone) %>% summarise(n = n())
## `summarise()` has grouped output by 'Month'. You can override using the
## `.groups` argument.
dq %>% ggplot(aes(x = Month, y = n)) +
geom_col(data = dq %>% filter( Month== '5'), fill = 'purple') +
geom_col(data = dq %>% filter(Month == '9'), fill = 'turquoise')

- Ta phân loại nồng độ theo các tháng sau đó tính số lượng .
- Ở biểu đồ trên thì ta gắn x là Month, y là nồng độ ozone của 2 tháng
5 và 9;
- Ta sẽ lọc nồng độ ozone của tháng 5, cột biểu đồ có màu tím và nồng
độ của tháng 9, biểu đồ có màu xanh ngọc.
- Tổng số lượng nồng độ ozone trong tháng 5 cao hơn so với tháng
9.
- Tổng số lượng nồng độ ozone trong tháng 5 với mức trung bình khoảng
31 ppb.
- Tổng số lượng nồng độ ozone trong tháng 9 với mức trung bình khoảng
30 ppb.
Đồ thị số 3
dq <- airquality
dq %>% ggplot(aes(x = Solar.R)) +
geom_histogram(binwidth = 10, fill = 'blue', color = 'red')
## Warning: Removed 7 rows containing non-finite values (`stat_bin()`).
- Biểu đồ thể hiện sự thay đổi cường độ bức xạ mặt trời
Đồ thị số 4
dq <- airquality
dq %>% ggplot(aes(x = Wind)) +
geom_density(fill = 'red')
- Qua biểu đồ ta thấy hầu hết tốc độ gió đều nằm trong khoảng 5 đến
15
- Ở mức tốc độ gió đạt 10mph có số lượng cao nhất
Đồ thị số 5
dq <- airquality
dq %>% group_by(Temp) %>% summarise(n = n()) %>%
ggplot(aes(x = '', y = n,fill = Temp)) +
geom_col(color = 'black') +
coord_polar('y') +
geom_text(aes(x = 1.3, label = n),position = position_stack(vjust = .5)) +
theme_void()

Biểu đồ biểu diễn số lượng từng mức nhiệt độ
Ở mức nhiệt độ càng cao thì có số lượng càng ít
Số lượng nhiệt độ nhiều nhất là 11 với mức nhiệt độ là từ 70 đến
80
Đồ thị số 6
dq <- airquality
dq %>% ggplot(aes(x = Day, y = Month, color = Solar.R)) +
geom_point()
- Biểu đồ biểu diễn bức xạ mặt trời theo từng tháng từ tháng 5 đến tháng
9
- Qua đồ thị ta thấy tháng 7 ,8 là những tháng có mức bức xạ cao nhất
với nhiều số lượng bức xạ từ 200 đến 300
Đồ thị số 7
dq <- airquality
dq %>% group_by(Temp) %>% summarise(n = n()) %>%
ggplot(aes(Temp,n)) +
geom_area(fill='skyblue') +
geom_text(aes(label = n),vjust = 2, color = 'red') +
labs(x = 'Nhiệt độ', y = 'Số lượng')
- Biểu đồ miền biểu diễn số lượng các mức nhiệt độ
Đồ thị số 8
dq <- airquality
dq %>% ggplot(aes(x = Temp)) +
geom_density(color = 'red', fill = 'skyblue')+
labs( x = 'Nhiệt độ')
- Qua biểu đồ ta thấy được: mật độ nhiệt độ phân phối không đồng đều
Đồ thị số 9
dq <- airquality
dq %>% group_by(Wind) %>% summarise(n = n()) %>%
ggplot(aes(Wind,n)) +
geom_bin2d(fill='pink') +
geom_text(aes(label = n),vjust = 2, color = 'black') +
labs(x = 'Tốc độ gió', y = 'Số lượng')
- Đây là biểu đồ mật độ 2D, chia dữ liệu thành các ô vuông, mỗi ô vuông
là 1 dữ liệu
Biểu đồ biểu diễn số lượng từng mức của tốc độ gió
Ở mức 5 đến 10 có số lượng tốc độ gió nhiều nhất
Ở mức 10 đến 15 chứa số lượng tốc độ gió cao nhất là 15
Đồ thị số 10
dq <- airquality
dq %>% ggplot(aes(x = Solar.R)) +
geom_density(color = 'black', fill = 'pink')+
labs( x = 'Bức xạ mặt trời')
## Warning: Removed 7 rows containing non-finite values (`stat_density()`).

Đồ thị số 11
dq <- airquality
dq %>% ggplot(aes(x = Ozone)) +
geom_density(color = 'red', fill = 'blue')+
labs( x = 'nồng độ ozone')
## Warning: Removed 37 rows containing non-finite values (`stat_density()`).
- Mật độ về nồng độ ozone tăng cao nhất ở khoảng dưới 50, sau đó giảm
dần xuống tận 150
- Vị trí có mật độ cao nhất nằm tầm khoảng 25
Đồ thị số 12
dq <- airquality
dq %>% group_by(Month) %>% summarise(m = mean(Wind)) %>%
ggplot(aes(x = Month,y = m)) +
geom_col(position = 'dodge') +
geom_text(aes(label = round(m))) +
labs(x = 'Tháng', y = 'Tốc độ gió trung bình')
- Biểu đồ biểu diễn tốc độ gió trung bình của từng tháng
- Tháng 5 có tốc độ trung bình cao nhất là 12
- Tháng 6 và tháng 9 có tốc độ gió trung bình bằng nhau là 10
- Tháng 7 và 8 có tốc độ gió trung bình bằng nhau là 9 và là thấp nhất trong 5 tháng
Đồ thị số 13
dq <- airquality
dq %>% ggplot(aes(x = Month, y = Temp)) +
geom_point(color = 'red') +
geom_smooth(method = 'lm', color = 'green')
## `geom_smooth()` using formula = 'y ~ x'
- Cho biết mối quan hệ của nhiệt độ theo từng tháng
Đồ thị số 14
dq <- airquality
dq %>% ggplot(aes(x= Month, y= Wind)) +
geom_area(fill="skyblue") +
labs(x='Tháng', y='Tốc độ gió')
- Biểu đồ diện tích thể hiện kích thước về tốc độ gió theo từng
tháng
Tốc độ gió tăng ở tháng 5 lên tháng 6
Có sự giảm sau khi đến tháng 7
Đến tháng 8 thì tăng lại và tháng 9 cũng tăng nhẹ # Đồ thị số
15
dq <- airquality
dq %>% ggplot(aes(x= Month, y= Ozone)) +
geom_bin_2d() +
labs(x='Tháng', y='Ozone')
## Warning: Removed 37 rows containing non-finite values (`stat_bin2d()`).
- Biểu đồ biểu diễn nồng độ ozone theo tháng
Nồng độ ozone thấp có màu đậm và nồng độ ozone cao thì màu càng
nhạt
Tháng 6 là tháng có nồng độ ozone thấp nhất
Tháng 8 có số lượng nồng độ ozone nhiều nhất
Đồ thị số 16
dq <- airquality
dq %>% ggplot(aes(x= Solar.R)) +
geom_dotplot() +
labs(x='Bức xạ mặt trời')
## Bin width defaults to 1/30 of the range of the data. Pick better value with
## `binwidth`.
## Warning: Removed 7 rows containing missing values (`stat_bindot()`).
- Mỗi chấm trên biểu đồ thể hiện một giá trị của bức xạ mặt trời
Đồ thị số 17
dq <- airquality
dq %>% group_by(Month) %>% summarise(m = mean(Temp)) %>%
ggplot(aes(x = Month,y = m)) +
geom_col(position = 'dodge') +
geom_text(aes(label = round(m))) +
labs(x = 'Tháng', y = 'Nhiệt độ trung bình')
- Biểu đồ biểu diễn nhiệt độ trung bình của từng tháng
Đồ thị số 18
dq <- airquality
dq <- dq %>% mutate(WindC = cut(Wind,5, label = c('rất nhỏ', 'nhỏ','vừa','lớn','rất lớn')))
dq %>% ggplot(aes(x = WindC)) +
geom_bar(fill = 'pink') +
coord_flip()
- Biểu đồ biểu diễn số lượng các cấp độ của tốc độ gió
Đồ thị số 19
dq <- airquality
dq <- dq %>% mutate(tempc = cut(Temp,3, label = c('nhỏ','vừa','lớn')))
dq %>% ggplot(aes(x = tempc)) +
geom_bar(fill = 'blue')
- Biểu đồ biểu diễn cấp độ của nhiệt độ
- Cấp độ vừa có số lượng nhiều nhất, sau đó tới lớn và ít nhất là
nhỏ
Đồ thị số 20
dq <- airquality
dq %>% ggplot(aes(x = Ozone)) +
geom_histogram(binwidth = 20, fill = 'blue', color = 'red')
## Warning: Removed 37 rows containing non-finite values (`stat_bin()`).

- Biểu đồ biểu diễn sự thay đổi của nồng độ Ozone
- Nồng độ Ozone phân phối không đồng đều
- Nồng độ ở mức dưới 50 là lớn nhất, sau đó giảm dần về 150
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSA1LiINCmF1dGhvcjogIk5ndXnhu4VuIERp4buFbSBRdeG7s25oIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUg6JU06JVMsICVkIC0gJW0gLSAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50Og0KICAgIGV4dHJhX2RlcGVuZGVuY2llczoNCiAgICAgIHZpZXRuYW06IHV0ZjgNCiAgICB0b2M6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgY2xhc3Muc291cmNlID0gIm51bWJlckxpbmVzIGxpbmVBbmNob3JzIiwgDQogIGNsYXNzLm91dHB1dCA9IGMoIm51bWJlckxpbmVzIGxpbmVBbmNob3JzIGNodW5rb3V0IikgDQopDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoRFQpDQoNCmBgYA0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQpkaXYuc291cmNlQ29kZSBwcmUuY2h1bmtvdXQgew0KICBiYWNrZ3JvdW5kOiB3aGl0ZTsNCn0NCmBgYA0KIA0KIyBUSMOUTkcgVElOIFbhu4AgQ0jhuqRUIEzGr+G7ok5HIEtIw5RORyBLSMONIFThuqBJIE5FVyBZT1JLIFThu6ogVEjDgU5HIDUgTsSCTSAxOTczIMSQ4bq+TiBUSMOBTkcgOSBOxIJNIDE5NzMNCg0KIy4gVGjDtG5nIHRpbiBi4buZIGThu68gbGnhu4d1DQoNCi0gT3pvbmU6IE7hu5NuZyDEkeG7mSBvem9uZSAoTzMpDQoNCi0gU29sYXIuUjogQuG7qWMgeOG6oSBt4bq3dCB0cuG7nWkNCg0KLSBXaW5kOiBU4buRYyDEkeG7mSBnacOzDQoNCi0gVGVtcDogTmhp4buHdCDEkeG7mQ0KDQotIE1vbnRoOiBUaMOhbmcNCg0KLSBEYXk6IE5nw6B5DQoNCi0gQuG7mSBk4buvIGxp4buHdSBjw7MgMTUzIHF1YW4gc8OhdCwgNiBiaeG6v24NCg0KDQpgYGB7cn0NCmxpYnJhcnkoZGF0YXNldHMpDQpkYXRhKHBhY2thZ2UgPSAnZGF0YXNldHMnKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZGF0YShwYWNrYWdlID0gJ2dncGxvdDInKQ0KZHEgPC0gYWlycXVhbGl0eQ0KYGBgDQoNCg0KIA0KIyDEkOG7kyB0aOG7iyBz4buRIDEgDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzY2FsZXMpDQogIGRxIDwtIGFpcnF1YWxpdHkNCiAgICBkcSAlPiUgZ3JvdXBfYnkoV2luZCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyhXaW5kLG4pKSArDQogICAgZ2VvbV9jb2woZmlsbD0nc2t5Ymx1ZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ1Thu5FjIMSR4buZIGdpw7MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogICAgDQogICAgDQogIC0gVGEgUGjDom4gbG/huqFpIHThu5FjIMSR4buZIGdpw7MgdGhlbyB04burbmcgbeG7qWMgxJHhu5kgdsOgIHTDrW5oIHPhu5EgbMaw4bujbmcgY+G7p2EgdOG7q25nIG3hu6ljIMSR4buZLg0KICANCiAgLSB4IGzDoCB04burbmcgbeG7qWMgxJHhu5kgY+G7p2EgdOG7kWMgxJHhu5kgZ2nDsywgeSBsw6Agc+G7kSBsxrDhu6NuZyBj4bunYSB04burbmcgbeG7qWMgLg0KICANCiAgLSBDw6FjIHPhu5EgbGnhu4d1IGPDsyBtw6B1IMSR4buPLCDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmgg4bufIHbhu4sgdHLDrSBk4buNYyBjw6FjaCBj4buZdCAyIMSRxqFuIHbhu4suIE3DoHUgY+G7p2EgY8OhYyBj4buZdCBsw6AgbcOgdSB4YW5oIGRhIHRy4budaS4NCiAgDQogIC0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buxIHBow6JuIGLhu5Egc+G7kSBsxrDhu6NuZyB0aGVvIHThu6tuZyBt4bupYyB04buRYyDEkeG7mSBnacOzLg0KICANCiAgLSBDw7MgbeG7mXQgc+G7kSBt4bupYyB04buRYyDEkeG7mSBnacOzIGPDsyBz4buRIGzGsOG7o25nIGNhbyBoxqFuLCBj4bulIHRo4buDIGzDoDoNCiAgDQogICAgICArIE3hu6ljIDUtMTAgbXBoIChk4bq3bS9naeG7nSkgY8OzIHPhu5EgbMaw4bujbmcgY2FvIG5o4bqldC4NCiAgICAgIA0KICAgICAgKyBN4bupYyAxMC0xNSBtcGggY8OzIHPhu5EgbMaw4bujbmcgY2FvIHRo4bupIGhhaS4NCiAgICAgIA0KICAtIEPDsyBt4buZdCBz4buRIG3hu6ljIHThu5FjIMSR4buZIGdpw7MgY8OzIHPhu5EgbMaw4bujbmcgdGjhuqVwIGjGoW4sIGPhu6UgdGjhu4MgbMOgOg0KICANCiAgICAgICsgTeG7qWMgZMaw4bubaSA1IG1waCB2w6AgdHLDqm4gMjAgbXBoIGPDsyBz4buRIGzGsOG7o25nIHRo4bqlcCBuaOG6pXQuDQogICAgDQogIA0KDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDINCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KZHEgPC0gZHEgJT4lIGdyb3VwX2J5KE1vbnRoLCBPem9uZSkgJT4lIHN1bW1hcmlzZShuID0gbigpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IE1vbnRoLCB5ID0gbikpICsNCiAgZ2VvbV9jb2woZGF0YSA9IGRxICU+JSBmaWx0ZXIoIE1vbnRoPT0gJzUnKSwgZmlsbCA9ICdwdXJwbGUnKSArDQogIGdlb21fY29sKGRhdGEgPSBkcSAlPiUgZmlsdGVyKE1vbnRoID09ICc5JyksIGZpbGwgPSAndHVycXVvaXNlJykNCmBgYA0KICANCiAgDQogIC0gVGEgcGjDom4gbG/huqFpIG7hu5NuZyDEkeG7mSB0aGVvIGPDoWMgdGjDoW5nIHNhdSDEkcOzIHTDrW5oIHPhu5EgbMaw4bujbmcgLiANCiAgLSDhu54gYmnhu4N1IMSR4buTIHRyw6puIHRow6wgdGEgZ+G6r24geCBsw6AgTW9udGgsIHkgbMOgIG7hu5NuZyDEkeG7mSBvem9uZSBj4bunYSAyIHRow6FuZyA1IHbDoCA5OyANCiAgLSBUYSBz4bq9IGzhu41jIG7hu5NuZyDEkeG7mSBvem9uZSBj4bunYSB0aMOhbmcgNSwgY+G7mXQgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHTDrW0gdsOgIG7hu5NuZyDEkeG7mSBj4bunYSB0aMOhbmcgOSwgYmnhu4N1IMSR4buTIGPDsyBtw6B1IHhhbmggbmfhu41jLiANCiAgLSBU4buVbmcgc+G7kSBsxrDhu6NuZyBu4buTbmcgxJHhu5kgb3pvbmUgdHJvbmcgdGjDoW5nIDUgY2FvIGjGoW4gc28gduG7m2kgdGjDoW5nIDkuDQogIC0gVOG7lW5nIHPhu5EgbMaw4bujbmcgbuG7k25nIMSR4buZIG96b25lIHRyb25nIHRow6FuZyA1IHbhu5tpIG3hu6ljIHRydW5nIGLDrG5oIGtob+G6o25nIDMxIHBwYi4NCiAgLSBU4buVbmcgc+G7kSBsxrDhu6NuZyBu4buTbmcgxJHhu5kgb3pvbmUgdHJvbmcgdGjDoW5nIDkgduG7m2kgbeG7qWMgdHJ1bmcgYsOsbmgga2hv4bqjbmcgMzAgcHBiLg0KDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDMNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gU29sYXIuUikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCwgZmlsbCA9ICdibHVlJywgY29sb3IgPSAncmVkJykNCg0KYGBgDQogIC0gQmnhu4N1IMSR4buTIHRo4buDIGhp4buHbiBz4buxIHRoYXkgxJHhu5VpIGPGsOG7nW5nIMSR4buZIGLhu6ljIHjhuqEgbeG6t3QgdHLhu51pIA0KICANCiAgLSBC4bupYyB44bqhIOG7nyBt4bupYyB04burIDIwMCDEkeG6v24gMzAwIGPDsyBjw7Mgc+G7kSBsxrDhu6NuZyBjxrDhu51uZyDEkeG7mSBsw6Agbmhp4buBdSBuaOG6pXQNCiAgDQogIC0gQuG7qWMgeOG6oSDhu58gbeG7qWMgdOG7qyAwIMSR4bq/biAxMDAgY8OzIGPDsyBz4buRIGzGsOG7o25nIGPGsOG7nW5nIMSR4buZIGzDoCDDrXQgbmjhuqV0DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDQNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gV2luZCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAncmVkJykNCmBgYA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IGjhuqd1IGjhur90IHThu5FjIMSR4buZIGdpw7MgxJHhu4F1IG7hurFtIHRyb25nIGtob+G6o25nIDUgxJHhur9uIDE1DQogIA0KICAtIOG7niBt4bupYyB04buRYyDEkeG7mSBnacOzIMSR4bqhdCAxMG1waCBjw7Mgc+G7kSBsxrDhu6NuZyBjYW8gbmjhuqV0DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDUNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ3JvdXBfYnkoVGVtcCkgJT4lIHN1bW1hcmlzZShuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gJycsIHkgPSBuLGZpbGwgPSBUZW1wKSkgKw0KICAgIGdlb21fY29sKGNvbG9yID0gJ2JsYWNrJykgKw0KICAgIGNvb3JkX3BvbGFyKCd5JykgKw0KICAgIGdlb21fdGV4dChhZXMoeCA9IDEuMywgbGFiZWwgPSBuKSxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gLjUpKSArDQogDQogICAgdGhlbWVfdm9pZCgpDQpgYGANCg0KICAtIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIHPhu5EgbMaw4bujbmcgdOG7q25nIG3hu6ljIG5oaeG7h3QgxJHhu5kNCiAgDQogIC0g4bueIG3hu6ljIG5oaeG7h3QgxJHhu5kgY8OgbmcgY2FvIHRow6wgY8OzIHPhu5EgbMaw4bujbmcgY8Ogbmcgw610DQogIA0KICAtIFPhu5EgbMaw4bujbmcgbmhp4buHdCDEkeG7mSBuaGnhu4F1IG5o4bqldCBsw6AgMTEgduG7m2kgbeG7qWMgbmhp4buHdCDEkeG7mSBsw6AgdOG7qyA3MCDEkeG6v24gODANCg0KIyDEkOG7kyB0aOG7iyBz4buRIDYNCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gRGF5LCB5ID0gTW9udGgsIGNvbG9yID0gU29sYXIuUikpICsNCiAgZ2VvbV9wb2ludCgpDQpgYGANCiAgLSBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiBi4bupYyB44bqhIG3hurd0IHRy4budaSB0aGVvIHThu6tuZyB0aMOhbmcgdOG7qyB0aMOhbmcgNSDEkeG6v24gdGjDoW5nIDkNCiAgDQogIC0gUXVhIMSR4buTIHRo4buLIHRhIHRo4bqleSB0aMOhbmcgNyAsOCBsw6Agbmjhu69uZyB0aMOhbmcgY8OzIG3hu6ljIGLhu6ljIHjhuqEgY2FvIG5o4bqldCB24bubaSBuaGnhu4F1IHPhu5EgbMaw4bujbmcgYuG7qWMgeOG6oSB04burIDIwMCDEkeG6v24gMzAwDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDcNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KICAgIGRxICU+JSBncm91cF9ieShUZW1wKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFRlbXAsbikpICsNCiAgICBnZW9tX2FyZWEoZmlsbD0nc2t5Ymx1ZScpICsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksdmp1c3QgPSAyLCBjb2xvciA9ICdyZWQnKSArDQogICAgbGFicyh4ID0gJ05oaeG7h3QgxJHhu5knLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogIC0gQmnhu4N1IMSR4buTIG1p4buBbiBiaeG7g3UgZGnhu4VuIHPhu5EgbMaw4bujbmcgY8OhYyBt4bupYyBuaGnhu4d0IMSR4buZDQogIA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IOG7nyBuaGnhu4d0IMSR4buZIDgwIMSR4buZIGPDsyBz4buRIGzGsOG7o25nIG5oaeG7gXUgbmjhuqV0IGzDoCAxMQ0KICANCiAgLSBT4buRIGzGsOG7o25nIGPDsyB4dSBoxrDhu5tuZyB0xINuZyBk4bqnbiB04burIG3hu6ljIDYwIMSR4bq/biA4MCB2w6Agc2F1IMSRw7MgZ2nhuqNtIGThuqduIHThu6sgODAgeHXhu5FuZyA5MA0KICANCiMgxJDhu5MgdGjhu4sgc+G7kSA4DQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCiAgICBkcSAlPiUgZ2dwbG90KGFlcyh4ID0gVGVtcCkpICsgDQogICAgICAgIGdlb21fZGVuc2l0eShjb2xvciA9ICdyZWQnLCBmaWxsID0gJ3NreWJsdWUnKSsNCiAgICAgICAgbGFicyggeCA9ICdOaGnhu4d0IMSR4buZJykNCmBgYA0KICAtIFF1YSBiaeG7g3UgxJHhu5MgdGEgdGjhuqV5IMSRxrDhu6NjOiBt4bqtdCDEkeG7mSBuaGnhu4d0IMSR4buZIHBow6JuIHBo4buRaSBraMO0bmcgxJHhu5NuZyDEkeG7gXUNCg0KICAtIE5oaeG7h3QgxJHhu5kg4bufIG3hu6ljIDgwIMSR4buZIGPDsyBt4bqtdCDEkeG7mSBjYW8gbmjhuqV0DQogIA0KICAtIE3hu6ljIG5oaeG7h3QgxJHhu5kgdOG7qyA2MCBjw7MgbeG6rXQgxJHhu5kgdMSDbmcgZOG6p24gxJHhur9uIDgwIMSR4buZIHNhdSDEkcOzIGdp4bqjbSBk4bqnbiB4deG7kW5nIDkwDQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDkNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KICAgIGRxICU+JSBncm91cF9ieShXaW5kKSAlPiUgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKFdpbmQsbikpICsNCiAgICBnZW9tX2JpbjJkKGZpbGw9J3BpbmsnKSArDQogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLHZqdXN0ID0gMiwgY29sb3IgPSAnYmxhY2snKSArDQogICAgbGFicyh4ID0gJ1Thu5FjIMSR4buZIGdpw7MnLCB5ID0gJ1Phu5EgbMaw4bujbmcnKQ0KYGBgDQogIC0gxJDDonkgbMOgIGJp4buDdSDEkeG7kyBt4bqtdCDEkeG7mSAyRCwgY2hpYSBk4buvIGxp4buHdSB0aMOgbmggY8OhYyDDtCB2dcO0bmcsIG3hu5dpIMO0IHZ1w7RuZyBsw6AgMSBk4buvIGxp4buHdQ0KICANCiAgLSAgQmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gc+G7kSBsxrDhu6NuZyB04burbmcgbeG7qWMgY+G7p2EgdOG7kWMgxJHhu5kgZ2nDsw0KICANCiAgLSDhu54gbeG7qWMgNSDEkeG6v24gMTAgY8OzIHPhu5EgbMaw4bujbmcgdOG7kWMgxJHhu5kgZ2nDsyBuaGnhu4F1IG5o4bqldA0KICANCiAgLSDhu54gbeG7qWMgMTAgxJHhur9uIDE1IGNo4bupYSBz4buRIGzGsOG7o25nIHThu5FjIMSR4buZIGdpw7MgY2FvIG5o4bqldCBsw6AgMTUNCiAgDQojIMSQ4buTIHRo4buLIHPhu5EgMTANCg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQogICAgZHEgJT4lIGdncGxvdChhZXMoeCA9IFNvbGFyLlIpKSArIA0KICAgICAgICBnZW9tX2RlbnNpdHkoY29sb3IgPSAnYmxhY2snLCBmaWxsID0gJ3BpbmsnKSsNCiAgICAgICAgbGFicyggeCA9ICdC4bupYyB44bqhIG3hurd0IHRy4budaScpDQpgYGANCg0KICAtIFF1YSDEkeG7kyB0aOG7iyB0YSB0aOG6pXkgbeG6rXQgxJHhu5kgYuG7qWMgeOG6oSBt4bq3dCB0cuG7nWkgY2FvIG5o4bqldCBu4bqxbSB2w6BvIGtob+G6o25nIDI1MCANCiAgDQogICAgLSBN4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkga2jDtG5nIMSR4buTbmcgxJHhu4F1LCB0xINuZyBnaeG6o20gbGnDqm4gdOG7pWMNCiAgICANCiMgxJDhu5MgdGjhu4sgc+G7kSAxMQ0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQogICAgZHEgJT4lIGdncGxvdChhZXMoeCA9IE96b25lKSkgKyANCiAgICAgICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gJ3JlZCcsIGZpbGwgPSAnYmx1ZScpKw0KICAgICAgICBsYWJzKCB4ID0gJ27hu5NuZyDEkeG7mSBvem9uZScpDQpgYGANCiAgLSBN4bqtdCDEkeG7mSB24buBIG7hu5NuZyDEkeG7mSBvem9uZSB0xINuZyBjYW8gbmjhuqV0IOG7nyBraG/huqNuZyBkxrDhu5tpIDUwLCBzYXUgxJHDsyBnaeG6o20gZOG6p24geHXhu5FuZyB04bqtbiAxNTANCiAgDQogIC0gVuG7iyB0csOtIGPDsyBt4bqtdCDEkeG7mSBjYW8gbmjhuqV0IG7hurFtIHThuqdtIGtob+G6o25nIDI1DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDEyDQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCmRxICU+JSBncm91cF9ieShNb250aCkgJT4lIHN1bW1hcmlzZShtID0gbWVhbihXaW5kKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IE1vbnRoLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtKSkpICsNCiAgICBsYWJzKHggPSAnVGjDoW5nJywgeSA9ICdU4buRYyDEkeG7mSBnacOzIHRydW5nIGLDrG5oJykNCiAgICAgICAgICAgICAgIA0KYGBgDQogICAgLSBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiB04buRYyDEkeG7mSBnacOzIHRydW5nIGLDrG5oIGPhu6dhIHThu6tuZyB0aMOhbmcNCiAgICANCiAgICAtIFRow6FuZyA1IGPDsyB04buRYyDEkeG7mSB0cnVuZyBiw6xuaCBjYW8gbmjhuqV0IGzDoCAxMg0KICAgIA0KICAgIC0gVGjDoW5nIDYgdsOgIHRow6FuZyA5IGPDsyB04buRYyDEkeG7mSBnacOzIHRydW5nIGLDrG5oIGLhurFuZyBuaGF1IGzDoCAxMA0KICAgIA0KICAgIC0gVGjDoW5nIDcgdsOgIDggY8OzIHThu5FjIMSR4buZIGdpw7MgdHJ1bmcgYsOsbmggYuG6sW5nIG5oYXUgbMOgIDkgdsOgIGzDoCB0aOG6pXAgbmjhuqV0IHRyb25nIDUgdGjDoW5nDQogIA0KICANCiMgxJDhu5MgdGjhu4sgc+G7kSAxMw0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gTW9udGgsIHkgPSBUZW1wKSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gJ3JlZCcpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAnZ3JlZW4nKQ0KYGBgDQogIC0gQ2hvIGJp4bq/dCBt4buRaSBxdWFuIGjhu4cgY+G7p2Egbmhp4buHdCDEkeG7mSB0aGVvIHThu6tuZyB0aMOhbmcNCiAgDQogIC0gVGjDoW5nIDUgY8OzIG5oaeG7h3QgxJHhu5kgdGjhuqVwIHNvIHbhu5tpIGPDoWMgdGjDoW5nIGPDsm4gbOG6oWkNCiAgDQogIC0gVGjDoW5nIDcsIDggY8OzIG5oaeG7h3QgxJHhu5kgdMawxqFuZyDEkeG7kWkgY2FvIA0KICANCg0KDQojIMSQ4buTIHRo4buLIHPhu5EgMTQNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eSANCmRxICU+JSBnZ3Bsb3QoYWVzKHg9IE1vbnRoLCB5PSBXaW5kKSkgKw0KIGdlb21fYXJlYShmaWxsPSJza3libHVlIikgKw0KDQogIGxhYnMoeD0nVGjDoW5nJywgeT0nVOG7kWMgxJHhu5kgZ2nDsycpDQpgYGANCiAgLSBCaeG7g3UgxJHhu5MgZGnhu4duIHTDrWNoIHRo4buDIGhp4buHbiBrw61jaCB0aMaw4bubYyB24buBIHThu5FjIMSR4buZIGdpw7MgdGhlbyB04burbmcgdGjDoW5nDQogIA0KICAtIFThu5FjIMSR4buZIGdpw7MgdMSDbmcg4bufIHRow6FuZyA1IGzDqm4gdGjDoW5nIDYNCiAgDQogIC0gQ8OzIHPhu7EgZ2nhuqNtIHNhdSBraGkgxJHhur9uIHRow6FuZyA3DQogIA0KICAtIMSQ4bq/biB0aMOhbmcgOCB0aMOsIHTEg25nIGzhuqFpIHbDoCB0aMOhbmcgOSBjxaluZyB0xINuZyBuaOG6uQ0KIyDEkOG7kyB0aOG7iyBz4buRIDE1DQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCmRxICU+JSBnZ3Bsb3QoYWVzKHg9IE1vbnRoLCB5PSBPem9uZSkpICsNCmdlb21fYmluXzJkKCkgKw0KICBsYWJzKHg9J1Row6FuZycsIHk9J096b25lJykNCmBgYA0KICAtIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIG7hu5NuZyDEkeG7mSBvem9uZSB0aGVvIHRow6FuZw0KICANCiAgLSBO4buTbmcgxJHhu5kgb3pvbmUgdGjhuqVwIGPDsyBtw6B1IMSR4bqtbSB2w6AgbuG7k25nIMSR4buZIG96b25lIGNhbyB0aMOsIG3DoHUgY8OgbmcgbmjhuqF0DQogIA0KICAtIFRow6FuZyA2IGzDoCB0aMOhbmcgY8OzIG7hu5NuZyDEkeG7mSBvem9uZSB0aOG6pXAgbmjhuqV0DQogIA0KICAtIFRow6FuZyA4IGPDsyBz4buRIGzGsOG7o25nIG7hu5NuZyDEkeG7mSBvem9uZSBuaGnhu4F1IG5o4bqldA0KICANCiMgxJDhu5MgdGjhu4sgc+G7kSAxNg0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4PSBTb2xhci5SKSkgKw0KZ2VvbV9kb3RwbG90KCkgKw0KICBsYWJzKHg9J0Lhu6ljIHjhuqEgbeG6t3QgdHLhu51pJykNCmBgYA0KICAtIE3hu5dpIGNo4bqlbSB0csOqbiBiaeG7g3UgxJHhu5MgdGjhu4MgaGnhu4duIG3hu5l0IGdpw6EgdHLhu4sgY+G7p2EgYuG7qWMgeOG6oSBt4bq3dCB0cuG7nWkNCiAgDQogIC0gQuG7qWMgeOG6oSB04burIDIwMCB04bubaSAzMDAgY8OzIHPhu5EgbMaw4bujbmcgbmhp4buBdSB2w6AgbeG6rXQgxJHhu5kgY2FvIA0KICANCiAgLSBC4bupYyB44bqhIHRyw6puIDMwMCBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgdsOgIG3huq10IMSR4buZIHRo4bqlcCBuaOG6pXQNCg0KIyDEkOG7kyB0aOG7iyBz4buRIDE3DQpgYGB7cn0NCmRxIDwtIGFpcnF1YWxpdHkNCmRxICU+JSBncm91cF9ieShNb250aCkgJT4lIHN1bW1hcmlzZShtID0gbWVhbihUZW1wKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IE1vbnRoLHkgPSBtKSkgKw0KICAgIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlJykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtKSkpICsNCiAgICBsYWJzKHggPSAnVGjDoW5nJywgeSA9ICdOaGnhu4d0IMSR4buZIHRydW5nIGLDrG5oJykNCmBgYA0KICAtIEJp4buDdSDEkeG7kyBiaeG7g3UgZGnhu4VuIG5oaeG7h3QgxJHhu5kgdHJ1bmcgYsOsbmggY+G7p2EgdOG7q25nIHRow6FuZw0KICANCiAgLSBOaGnhu4d0IMSR4buZIHRydW5nIGLDrG5oIHRow6FuZyA3IHbDoCB0aMOhbmcgOCBsw6AgYuG6sW5nIG5oYXU6IDg0DQogIA0KICAtIE5oaeG7h3QgxJHhu5kgdHJ1bmcgYsOsbmggdGjDoW5nIDYgbMOgIG5o4buPIG5o4bqldDogNjYNCiAgDQojIMSQ4buTIHRo4buLIHPhu5EgMTgNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KZHEgPC0gZHEgJT4lIG11dGF0ZShXaW5kQyA9IGN1dChXaW5kLDUsIGxhYmVsID0gYygncuG6pXQgbmjhu48nLCAnbmjhu48nLCd24burYScsJ2zhu5tuJywncuG6pXQgbOG7m24nKSkpDQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gV2luZEMpKSArDQogIGdlb21fYmFyKGZpbGwgPSAncGluaycpICsNCmNvb3JkX2ZsaXAoKQ0KYGBgDQogIC0gQmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gc+G7kSBsxrDhu6NuZyBjw6FjIGPhuqVwIMSR4buZIGPhu6dhIHThu5FjIMSR4buZIGdpw7MNCiAgDQogIC0gVOG7kWMgxJHhu5kgZ2nDsyBuaOG7jyBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCBzYXUgxJHDsyDEkeG6v24gduG7q2ENCiAgDQogIC0gVOG7kWMgxJHhu5kgZ2nDsyBy4bqldCBs4bubbiBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQgbmjhuqV0DQogIA0KIyDEkOG7kyB0aOG7iyBz4buRIDE5DQoNCmBgYHtyfQ0KZHEgPC0gYWlycXVhbGl0eQ0KZHEgPC0gZHEgJT4lIG11dGF0ZSh0ZW1wYyA9IGN1dChUZW1wLDMsIGxhYmVsID0gYygnbmjhu48nLCd24burYScsJ2zhu5tuJykpKQ0KZHEgJT4lIGdncGxvdChhZXMoeCA9IHRlbXBjKSkgKw0KICBnZW9tX2JhcihmaWxsID0gJ2JsdWUnKSANCg0KYGBgDQogIC0gQmnhu4N1IMSR4buTIGJp4buDdSBkaeG7hW4gY+G6pXAgxJHhu5kgY+G7p2Egbmhp4buHdCDEkeG7mQ0KICANCiAgLSBD4bqlcCDEkeG7mSB24burYSBjw7Mgc+G7kSBsxrDhu6NuZyBuaGnhu4F1IG5o4bqldCwgc2F1IMSRw7MgdOG7m2kgbOG7m24gdsOgIMOtdCBuaOG6pXQgbMOgIG5o4buPDQoNCiMgxJDhu5MgdGjhu4sgc+G7kSAyMA0KYGBge3J9DQpkcSA8LSBhaXJxdWFsaXR5DQpkcSAlPiUgZ2dwbG90KGFlcyh4ID0gT3pvbmUpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjAsIGZpbGwgPSAnYmx1ZScsIGNvbG9yID0gJ3JlZCcpDQoNCmBgYA0KDQogICAgLSBCaeG7g3UgxJHhu5MgYmnhu4N1IGRp4buFbiBz4buxIHRoYXkgxJHhu5VpIGPhu6dhIG7hu5NuZyDEkeG7mSBPem9uZQ0KICAgIA0KICAgIC0gTuG7k25nIMSR4buZIE96b25lIHBow6JuIHBo4buRaSBraMO0bmcgxJHhu5NuZyDEkeG7gXUNCiAgICANCiAgICAtIE7hu5NuZyDEkeG7mSDhu58gbeG7qWMgZMaw4bubaSA1MCBsw6AgbOG7m24gbmjhuqV0LCBzYXUgxJHDsyBnaeG6o20gZOG6p24gduG7gSAxNTA=