# Read the CSV data
data <- read.csv("/Users/liuyutong/Desktop/0310INFS/housing.csv", header = TRUE, stringsAsFactors = FALSE)
# View the structure of the data to understand the column names and types
str(data)
'data.frame': 90 obs. of 28 variables:
$ Neighborhood : chr "Allegheny Center" "Allegheny West" "Allentown" "Arlington" ...
$ Sector.. : int 3 3 6 7 7 5 15 5 6 12 ...
$ Population..2010. : chr "933" "462" "2,500" "1,869" ...
$ Total...Units..2000. : chr "675" "390" "1,505" "880" ...
$ Total_Units_2010 : chr "1,052" "355" "1,291" "886" ...
$ X..Occupied.Units..2010. : chr "51.5%" "74.9%" "80.0%" "86.6%" ...
$ X..Vacant.Units..2010. : chr "48.5%" "25.1%" "20.0%" "13.4%" ...
$ X..Occupied.Units..2010..1 : chr "535" "203" "953" "754" ...
$ X..Owner.Occupied.Units..2010. : chr "10.1%" "18.2%" "59.2%" "65.4%" ...
$ Percent_Renter_Occupied_Units_2010 : chr "89.9%" "81.8%" "40.8%" "34.6%" ...
$ Est..Avg..Yrs..of.Residence..2010. : int 0 15 5 11 2 5 2 6 17 3 ...
$ X..Living.in.Household..2010. : chr "100.0%" "100.0%" "92.1%" "100.0%" ...
$ X..Living.in.Group.Quarters..2010. : chr "0.0%" "0.0%" "7.9%" "0.0%" ...
$ X..Units.Built.00.09 : chr "4.6%" "0.0%" "0.0%" "0.0%" ...
$ X..Units.Built.90.99 : chr "2.1%" "3.6%" "1.5%" "1.1%" ...
$ X..Units.Built.80.89 : chr "7.4%" "0.0%" "8.2%" "1.6%" ...
$ X..Units.Built.60.79 : chr "67.3%" "7.9%" "7.1%" "0.5%" ...
$ X..Units.Built.40.59 : chr "17.3%" "31.0%" "20.3%" "24.5%" ...
$ X..Units.Built.before.1939 : chr "1.3%" "57.4%" "62.9%" "72.3%" ...
$ Median.Home.Value..2000. : chr "US$86,500" "US$159,700" "US$34,300" "US$38,800" ...
$ Med..Val....00.in..10.Dollars. : chr "US$109,535" "US$202,228" "US$43,434" "US$49,132" ...
$ Median.Home..Value..2010. : chr "US$136,300" "US$123,600" "US$42,200" "US$44,200" ...
$ X..Change.Real.Value.2000.2010 : chr "24.4%" "-38.9%" "-2.8%" "-10.0%" ...
$ Median.Sale.Price..2010. : chr "N/A" "US$309,940" "US$8,500" "US$15,397" ...
$ X..Sales.Counted..2010. : int 0 7 70 34 0 40 1 128 39 118 ...
$ Foreclosures..2008. : int 0 0 27 12 0 7 0 64 12 18 ...
$ Foreclosures..2010. : int 0 1 11 13 0 5 1 40 11 12 ...
$ X..of.all.Housing.Units.Foreclosed..2010.: chr "0.0%" "0.3%" "0.9%" "1.5%" ...
# Convert 'Total_Units_2010' to numeric. This is important if it's not already numeric.
# If the column is a factor or character, this step will convert it to numeric.
data$Total_Units_2010 <- as.numeric(as.character(data$Total_Units_2010))
Warning: NAs introduced by coercion
# Convert 'Percent_Renter_Occupied_Units_2010' to numeric after removing the percent sign.
# This step will remove the '%' sign and convert the result to numeric.
data$Percent_Renter_Occupied_Units_2010 <- as.numeric(gsub("%", "", data$Percent_Renter_Occupied_Units_2010))
# Check for any conversion errors that might have resulted in NAs in either column
sum(is.na(data$Total_Units_2010))
[1] 56
sum(is.na(data$Percent_Renter_Occupied_Units_2010))
[1] 0
# Calculate the rentable properties
rentable_properties <- data$Total_Units_2010 * (data$Percent_Renter_Occupied_Units_2010 / 100)
# Print the calculated rentable properties
print(rentable_properties)
[1] NA 290.390 NA 306.556 120.324 NA 689.304 NA NA NA 243.664
[12] 58.437 NA NA 220.080 NA NA NA NA NA 23.128 4.000
[23] NA NA NA NA 70.531 NA NA NA 61.752 289.440 341.240
[34] NA NA 228.333 NA 41.818 NA NA NA NA 379.848 NA
[45] 418.348 NA NA NA NA NA NA NA NA 75.168 41.184
[56] NA 241.000 723.000 320.902 NA NA NA NA NA 376.107 116.876
[67] 51.666 NA NA NA 15.000 NA NA 268.824 NA NA NA
[78] 91.575 NA 297.990 180.030 81.250 NA NA NA NA 109.065 423.192
[89] NA 59.719
# Assuming there's a column 'Neighborhood' in your data
# Create a new data frame with relevant information
result_df <- data.frame(
Neighborhood = data$Neighborhood,
Total_Units = data$Total_Units_2010,
Percent_Renter_Occupied = data$Percent_Renter_Occupied_Units_2010,
RentableProperty = rentable_properties
)
# Remove rows with NA in RentableProperty
result_df <- na.omit(result_df)
# Print the first few rows of the result
print(result_df)
# Round down the RentableProperty values to the nearest whole number
result_df$RentableProperty <- floor(result_df$RentableProperty)
# Now, let's print the first few rows of the updated result
print(result_df)
NA
# Continuing from where we calculated rentable_properties
# Replace NA values in rentable_properties with 0
rentable_properties[is.na(rentable_properties)] <- 0
# Round down the RentableProperty values to the nearest whole number
rentable_properties <- floor(rentable_properties)
# Create a new data frame with relevant information
result_df <- data.frame(
Neighborhood = data$Neighborhood,
Total_Units = data$Total_Units_2010,
Percent_Renter_Occupied = data$Percent_Renter_Occupied_Units_2010,
RentableProperty = rentable_properties
)
# Now, let's print the first few rows of the result
print(result_df)
NA
# Read the CSV data
data <- read.csv("/Users/liuyutong/Desktop/0310INFS/housing.csv", header = TRUE, stringsAsFactors = FALSE)
# Remove quotes from 'Total_Units_2010' and convert to numeric
# This strips out double quotes and then converts the result to numeric
data$Total_Units_2010 <- as.numeric(gsub("\"", "", data$Total_Units_2010))
Warning: NAs introduced by coercion
# Remove percent sign from 'Percent_Renter_Occupied_Units_2010' and convert to numeric
data$Percent_Renter_Occupied_Units_2010 <- as.numeric(gsub("%", "", data$Percent_Renter_Occupied_Units_2010))
# Calculate the rentable properties, handling NAs
rentable_properties <- with(data, Total_Units_2010 * (Percent_Renter_Occupied_Units_2010 / 100))
rentable_properties[is.na(rentable_properties)] <- 0
# Round down the RentableProperty values to the nearest whole number
rentable_properties <- floor(rentable_properties)
# Create a new data frame with relevant information
result_df <- data.frame(
Neighborhood = data$Neighborhood,
Total_Units = data$Total_Units_2010,
Percent_Renter_Occupied = data$Percent_Renter_Occupied_Units_2010,
RentableProperty = rentable_properties
)
# Print the first few rows of the result
print(result_df)
# Load necessary libraries
library(tidyverse)
library(conflicted)
# Try reading the file with fill = TRUE to handle rows with different lengths
data <- read.csv("~/Desktop/0310INFS/project_dataset.csv", header = TRUE, fill = TRUE)
# Check the structure of the loaded data
str(data)
'data.frame': 39 obs. of 6 variables:
$ Neighborhood : chr "Central Business Center" "Bluff" "Strip District" "Crawford-Roberts" ...
$ Mean.Incidents.reported : num 300.2 56.2 45.6 57 25 ...
$ Average.rent.... : int 1966 1840 1961 1840 1840 1840 1786 1751 1786 1751 ...
$ Distance.to.Campus..Miles.: num 3.3 2.2 3.7 2.3 2 2.1 1.1 0.4 0.8 0.5 ...
$ Rentable.Property : int 1779 243 297 958 689 623 1462 2659 423 2181 ...
$ Population : int 5477 5882 1845 2293 1386 1757 2320 10691 2534 5835 ...
# Simple Linear Regression
model <- lm(Mean.Incidents.reported ~ Rentable.Property, data = data)
# Display the summary of the model
summary(model)
Call:
lm(formula = Mean.Incidents.reported ~ Rentable.Property, data = data)
Residuals:
Min 1Q Median 3Q Max
-31.707 -18.274 -10.902 3.935 248.784
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 24.989248 10.044926 2.488 0.0175 *
Rentable.Property 0.014855 0.006025 2.466 0.0184 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 44.99 on 37 degrees of freedom
Multiple R-squared: 0.1411, Adjusted R-squared: 0.1179
F-statistic: 6.079 on 1 and 37 DF, p-value: 0.01844
# Diagnostic plots
par(mfrow = c(2, 2))
plot(model)

# Load necessary libraries
library(ggplot2)
# Assuming you have a dataframe called 'data' with the variables of interest
# data <- read.csv('path_to_your_data.csv') # Uncomment and set path to your data file
# Simple Linear Regression
model <- lm(Mean.Incidents.reported ~ Rentable.Property, data = data)
# Summary of the model
summary(model)
Call:
lm(formula = Mean.Incidents.reported ~ Rentable.Property, data = data)
Residuals:
Min 1Q Median 3Q Max
-31.707 -18.274 -10.902 3.935 248.784
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 24.989248 10.044926 2.488 0.0175 *
Rentable.Property 0.014855 0.006025 2.466 0.0184 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 44.99 on 37 degrees of freedom
Multiple R-squared: 0.1411, Adjusted R-squared: 0.1179
F-statistic: 6.079 on 1 and 37 DF, p-value: 0.01844
# Plotting the data with ggplot2
ggplot(data, aes(x=Mean.Incidents.reported, y=Rentable.Property)) +
geom_point() + # This adds the scatter plot points
geom_smooth(method='lm', se=FALSE) + # This adds the regression line
labs(title='Linear Regression of Incident Reports on Number of Rentable Properties',
x='Number of Rentable Properties',
y='Number of Incident Reports') +
theme_minimal()
# Save the plot to a file
ggsave('regression_plot.png', width=8, height=6)

# Load necessary library
library(dplyr)
# First, sort the neighborhoods by the number of rentable properties
sorted_data <- data %>%
arrange(desc(Rentable.Property))
# Print the top 5 neighborhoods
top_5_neighborhoods <- head(sorted_data, 5)
print(top_5_neighborhoods)
# Create a bar graph of all neighborhoods ranked by rentable properties
ggplot(sorted_data, aes(x=reorder(Neighborhood, Rentable.Property), y=Rentable.Property)) +
geom_bar(stat='identity') +
labs(title='Neighborhoods Ranked by Number of Rentable Properties',
x='Neighborhood',
y='Number of Rentable Properties') +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) # Rotate the x labels for readability

LS0tCnRpdGxlOiAiMDMxMCBGaW5hbCBwcm9qZWN0IFJlbnRhYmxlIFByb3BlcnR5IE1ldHJpYyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KIyBSZWFkIHRoZSBDU1YgZGF0YQpkYXRhIDwtIHJlYWQuY3N2KCIvVXNlcnMvbGl1eXV0b25nL0Rlc2t0b3AvMDMxMElORlMvaG91c2luZy5jc3YiLCBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIFZpZXcgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YSB0byB1bmRlcnN0YW5kIHRoZSBjb2x1bW4gbmFtZXMgYW5kIHR5cGVzCnN0cihkYXRhKQoKIyBDb252ZXJ0ICdUb3RhbF9Vbml0c18yMDEwJyB0byBudW1lcmljLiBUaGlzIGlzIGltcG9ydGFudCBpZiBpdCdzIG5vdCBhbHJlYWR5IG51bWVyaWMuCiMgSWYgdGhlIGNvbHVtbiBpcyBhIGZhY3RvciBvciBjaGFyYWN0ZXIsIHRoaXMgc3RlcCB3aWxsIGNvbnZlcnQgaXQgdG8gbnVtZXJpYy4KZGF0YSRUb3RhbF9Vbml0c18yMDEwIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGRhdGEkVG90YWxfVW5pdHNfMjAxMCkpCgojIENvbnZlcnQgJ1BlcmNlbnRfUmVudGVyX09jY3VwaWVkX1VuaXRzXzIwMTAnIHRvIG51bWVyaWMgYWZ0ZXIgcmVtb3ZpbmcgdGhlIHBlcmNlbnQgc2lnbi4KIyBUaGlzIHN0ZXAgd2lsbCByZW1vdmUgdGhlICclJyBzaWduIGFuZCBjb252ZXJ0IHRoZSByZXN1bHQgdG8gbnVtZXJpYy4KZGF0YSRQZXJjZW50X1JlbnRlcl9PY2N1cGllZF9Vbml0c18yMDEwIDwtIGFzLm51bWVyaWMoZ3N1YigiJSIsICIiLCBkYXRhJFBlcmNlbnRfUmVudGVyX09jY3VwaWVkX1VuaXRzXzIwMTApKQoKIyBDaGVjayBmb3IgYW55IGNvbnZlcnNpb24gZXJyb3JzIHRoYXQgbWlnaHQgaGF2ZSByZXN1bHRlZCBpbiBOQXMgaW4gZWl0aGVyIGNvbHVtbgpzdW0oaXMubmEoZGF0YSRUb3RhbF9Vbml0c18yMDEwKSkKc3VtKGlzLm5hKGRhdGEkUGVyY2VudF9SZW50ZXJfT2NjdXBpZWRfVW5pdHNfMjAxMCkpCgojIENhbGN1bGF0ZSB0aGUgcmVudGFibGUgcHJvcGVydGllcwpyZW50YWJsZV9wcm9wZXJ0aWVzIDwtIGRhdGEkVG90YWxfVW5pdHNfMjAxMCAqIChkYXRhJFBlcmNlbnRfUmVudGVyX09jY3VwaWVkX1VuaXRzXzIwMTAgLyAxMDApCgojIFByaW50IHRoZSBjYWxjdWxhdGVkIHJlbnRhYmxlIHByb3BlcnRpZXMKcHJpbnQocmVudGFibGVfcHJvcGVydGllcykKCmBgYAoKYGBge3J9CiMgQXNzdW1pbmcgdGhlcmUncyBhIGNvbHVtbiAnTmVpZ2hib3Job29kJyBpbiB5b3VyIGRhdGEKIyBDcmVhdGUgYSBuZXcgZGF0YSBmcmFtZSB3aXRoIHJlbGV2YW50IGluZm9ybWF0aW9uCnJlc3VsdF9kZiA8LSBkYXRhLmZyYW1lKAogIE5laWdoYm9yaG9vZCA9IGRhdGEkTmVpZ2hib3Job29kLCAKICBUb3RhbF9Vbml0cyA9IGRhdGEkVG90YWxfVW5pdHNfMjAxMCwgCiAgUGVyY2VudF9SZW50ZXJfT2NjdXBpZWQgPSBkYXRhJFBlcmNlbnRfUmVudGVyX09jY3VwaWVkX1VuaXRzXzIwMTAsIAogIFJlbnRhYmxlUHJvcGVydHkgPSByZW50YWJsZV9wcm9wZXJ0aWVzCikKCiMgUmVtb3ZlIHJvd3Mgd2l0aCBOQSBpbiBSZW50YWJsZVByb3BlcnR5CnJlc3VsdF9kZiA8LSBuYS5vbWl0KHJlc3VsdF9kZikKCiMgUHJpbnQgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSByZXN1bHQKcHJpbnQocmVzdWx0X2RmKQpgYGAKCmBgYHtyfQojIFJvdW5kIGRvd24gdGhlIFJlbnRhYmxlUHJvcGVydHkgdmFsdWVzIHRvIHRoZSBuZWFyZXN0IHdob2xlIG51bWJlcgpyZXN1bHRfZGYkUmVudGFibGVQcm9wZXJ0eSA8LSBmbG9vcihyZXN1bHRfZGYkUmVudGFibGVQcm9wZXJ0eSkKCiMgTm93LCBsZXQncyBwcmludCB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgdGhlIHVwZGF0ZWQgcmVzdWx0CnByaW50KHJlc3VsdF9kZikKCmBgYAoKYGBge3J9CiMgQ29udGludWluZyBmcm9tIHdoZXJlIHdlIGNhbGN1bGF0ZWQgcmVudGFibGVfcHJvcGVydGllcwoKIyBSZXBsYWNlIE5BIHZhbHVlcyBpbiByZW50YWJsZV9wcm9wZXJ0aWVzIHdpdGggMApyZW50YWJsZV9wcm9wZXJ0aWVzW2lzLm5hKHJlbnRhYmxlX3Byb3BlcnRpZXMpXSA8LSAwCgojIFJvdW5kIGRvd24gdGhlIFJlbnRhYmxlUHJvcGVydHkgdmFsdWVzIHRvIHRoZSBuZWFyZXN0IHdob2xlIG51bWJlcgpyZW50YWJsZV9wcm9wZXJ0aWVzIDwtIGZsb29yKHJlbnRhYmxlX3Byb3BlcnRpZXMpCgojIENyZWF0ZSBhIG5ldyBkYXRhIGZyYW1lIHdpdGggcmVsZXZhbnQgaW5mb3JtYXRpb24KcmVzdWx0X2RmIDwtIGRhdGEuZnJhbWUoCiAgTmVpZ2hib3Job29kID0gZGF0YSROZWlnaGJvcmhvb2QsIAogIFRvdGFsX1VuaXRzID0gZGF0YSRUb3RhbF9Vbml0c18yMDEwLCAKICBQZXJjZW50X1JlbnRlcl9PY2N1cGllZCA9IGRhdGEkUGVyY2VudF9SZW50ZXJfT2NjdXBpZWRfVW5pdHNfMjAxMCwgCiAgUmVudGFibGVQcm9wZXJ0eSA9IHJlbnRhYmxlX3Byb3BlcnRpZXMKKQoKIyBOb3csIGxldCdzIHByaW50IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgcmVzdWx0CnByaW50KHJlc3VsdF9kZikKCmBgYAoKYGBge3J9CiMgUmVhZCB0aGUgQ1NWIGRhdGEKZGF0YSA8LSByZWFkLmNzdigiL1VzZXJzL2xpdXl1dG9uZy9EZXNrdG9wLzAzMTBJTkZTL2hvdXNpbmcuY3N2IiwgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBSZW1vdmUgcXVvdGVzIGZyb20gJ1RvdGFsX1VuaXRzXzIwMTAnIGFuZCBjb252ZXJ0IHRvIG51bWVyaWMKIyBUaGlzIHN0cmlwcyBvdXQgZG91YmxlIHF1b3RlcyBhbmQgdGhlbiBjb252ZXJ0cyB0aGUgcmVzdWx0IHRvIG51bWVyaWMKZGF0YSRUb3RhbF9Vbml0c18yMDEwIDwtIGFzLm51bWVyaWMoZ3N1YigiXCIiLCAiIiwgZGF0YSRUb3RhbF9Vbml0c18yMDEwKSkKCiMgUmVtb3ZlIHBlcmNlbnQgc2lnbiBmcm9tICdQZXJjZW50X1JlbnRlcl9PY2N1cGllZF9Vbml0c18yMDEwJyBhbmQgY29udmVydCB0byBudW1lcmljCmRhdGEkUGVyY2VudF9SZW50ZXJfT2NjdXBpZWRfVW5pdHNfMjAxMCA8LSBhcy5udW1lcmljKGdzdWIoIiUiLCAiIiwgZGF0YSRQZXJjZW50X1JlbnRlcl9PY2N1cGllZF9Vbml0c18yMDEwKSkKCiMgQ2FsY3VsYXRlIHRoZSByZW50YWJsZSBwcm9wZXJ0aWVzLCBoYW5kbGluZyBOQXMKcmVudGFibGVfcHJvcGVydGllcyA8LSB3aXRoKGRhdGEsIFRvdGFsX1VuaXRzXzIwMTAgKiAoUGVyY2VudF9SZW50ZXJfT2NjdXBpZWRfVW5pdHNfMjAxMCAvIDEwMCkpCnJlbnRhYmxlX3Byb3BlcnRpZXNbaXMubmEocmVudGFibGVfcHJvcGVydGllcyldIDwtIDAKCiMgUm91bmQgZG93biB0aGUgUmVudGFibGVQcm9wZXJ0eSB2YWx1ZXMgdG8gdGhlIG5lYXJlc3Qgd2hvbGUgbnVtYmVyCnJlbnRhYmxlX3Byb3BlcnRpZXMgPC0gZmxvb3IocmVudGFibGVfcHJvcGVydGllcykKCiMgQ3JlYXRlIGEgbmV3IGRhdGEgZnJhbWUgd2l0aCByZWxldmFudCBpbmZvcm1hdGlvbgpyZXN1bHRfZGYgPC0gZGF0YS5mcmFtZSgKICBOZWlnaGJvcmhvb2QgPSBkYXRhJE5laWdoYm9yaG9vZCwgCiAgVG90YWxfVW5pdHMgPSBkYXRhJFRvdGFsX1VuaXRzXzIwMTAsIAogIFBlcmNlbnRfUmVudGVyX09jY3VwaWVkID0gZGF0YSRQZXJjZW50X1JlbnRlcl9PY2N1cGllZF9Vbml0c18yMDEwLCAKICBSZW50YWJsZVByb3BlcnR5ID0gcmVudGFibGVfcHJvcGVydGllcwopCgojIFByaW50IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgcmVzdWx0CnByaW50KHJlc3VsdF9kZikKYGBgCgpgYGB7cn0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY29uZmxpY3RlZCkKIyBUcnkgcmVhZGluZyB0aGUgZmlsZSB3aXRoIGZpbGwgPSBUUlVFIHRvIGhhbmRsZSByb3dzIHdpdGggZGlmZmVyZW50IGxlbmd0aHMKZGF0YSA8LSByZWFkLmNzdigifi9EZXNrdG9wLzAzMTBJTkZTL3Byb2plY3RfZGF0YXNldC5jc3YiLCBoZWFkZXIgPSBUUlVFLCBmaWxsID0gVFJVRSkKCiMgQ2hlY2sgdGhlIHN0cnVjdHVyZSBvZiB0aGUgbG9hZGVkIGRhdGEKc3RyKGRhdGEpCmBgYAoKCmBgYHtyfQojIFNpbXBsZSBMaW5lYXIgUmVncmVzc2lvbgptb2RlbCA8LSBsbShNZWFuLkluY2lkZW50cy5yZXBvcnRlZCB+IFJlbnRhYmxlLlByb3BlcnR5LCBkYXRhID0gZGF0YSkKCiMgRGlzcGxheSB0aGUgc3VtbWFyeSBvZiB0aGUgbW9kZWwKc3VtbWFyeShtb2RlbCkKCiMgRGlhZ25vc3RpYyBwbG90cwpwYXIobWZyb3cgPSBjKDIsIDIpKQpwbG90KG1vZGVsKQoKYGBgCgpgYGB7cn0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKbGlicmFyeShnZ3Bsb3QyKQoKIyBBc3N1bWluZyB5b3UgaGF2ZSBhIGRhdGFmcmFtZSBjYWxsZWQgJ2RhdGEnIHdpdGggdGhlIHZhcmlhYmxlcyBvZiBpbnRlcmVzdAojIGRhdGEgPC0gcmVhZC5jc3YoJ3BhdGhfdG9feW91cl9kYXRhLmNzdicpICAjIFVuY29tbWVudCBhbmQgc2V0IHBhdGggdG8geW91ciBkYXRhIGZpbGUKCiMgU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uCm1vZGVsIDwtIGxtKE1lYW4uSW5jaWRlbnRzLnJlcG9ydGVkIH4gUmVudGFibGUuUHJvcGVydHksIGRhdGEgPSBkYXRhKQoKIyBTdW1tYXJ5IG9mIHRoZSBtb2RlbApzdW1tYXJ5KG1vZGVsKQoKIyBQbG90dGluZyB0aGUgZGF0YSB3aXRoIGdncGxvdDIKZ2dwbG90KGRhdGEsIGFlcyh4PU1lYW4uSW5jaWRlbnRzLnJlcG9ydGVkLCB5PVJlbnRhYmxlLlByb3BlcnR5KSkgKwogIGdlb21fcG9pbnQoKSArICAjIFRoaXMgYWRkcyB0aGUgc2NhdHRlciBwbG90IHBvaW50cwogIGdlb21fc21vb3RoKG1ldGhvZD0nbG0nLCBzZT1GQUxTRSkgKyAgIyBUaGlzIGFkZHMgdGhlIHJlZ3Jlc3Npb24gbGluZQogIGxhYnModGl0bGU9J0xpbmVhciBSZWdyZXNzaW9uIG9mIEluY2lkZW50IFJlcG9ydHMgb24gTnVtYmVyIG9mIFJlbnRhYmxlIFByb3BlcnRpZXMnLAogICAgICAgeD0nTnVtYmVyIG9mIFJlbnRhYmxlIFByb3BlcnRpZXMnLCAKICAgICAgIHk9J051bWJlciBvZiBJbmNpZGVudCBSZXBvcnRzJykgKwogIHRoZW1lX21pbmltYWwoKQoKIyBTYXZlIHRoZSBwbG90IHRvIGEgZmlsZQpnZ3NhdmUoJ3JlZ3Jlc3Npb25fcGxvdC5wbmcnLCB3aWR0aD04LCBoZWlnaHQ9NikKCmBgYAoKCmBgYHtyfQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcnkKbGlicmFyeShkcGx5cikKCiMgRmlyc3QsIHNvcnQgdGhlIG5laWdoYm9yaG9vZHMgYnkgdGhlIG51bWJlciBvZiByZW50YWJsZSBwcm9wZXJ0aWVzCnNvcnRlZF9kYXRhIDwtIGRhdGEgJT4lCiAgYXJyYW5nZShkZXNjKFJlbnRhYmxlLlByb3BlcnR5KSkKCiMgUHJpbnQgdGhlIHRvcCA1IG5laWdoYm9yaG9vZHMKdG9wXzVfbmVpZ2hib3Job29kcyA8LSBoZWFkKHNvcnRlZF9kYXRhLCA1KQpwcmludCh0b3BfNV9uZWlnaGJvcmhvb2RzKQoKIyBDcmVhdGUgYSBiYXIgZ3JhcGggb2YgYWxsIG5laWdoYm9yaG9vZHMgcmFua2VkIGJ5IHJlbnRhYmxlIHByb3BlcnRpZXMKZ2dwbG90KHNvcnRlZF9kYXRhLCBhZXMoeD1yZW9yZGVyKE5laWdoYm9yaG9vZCwgUmVudGFibGUuUHJvcGVydHkpLCB5PVJlbnRhYmxlLlByb3BlcnR5KSkgKwogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5JykgKwogIGxhYnModGl0bGU9J05laWdoYm9yaG9vZHMgUmFua2VkIGJ5IE51bWJlciBvZiBSZW50YWJsZSBQcm9wZXJ0aWVzJywKICAgICAgIHg9J05laWdoYm9yaG9vZCcsIAogICAgICAgeT0nTnVtYmVyIG9mIFJlbnRhYmxlIFByb3BlcnRpZXMnKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHRoZSB4IGxhYmVscyBmb3IgcmVhZGFiaWxpdHkKYGBg