# The idea to rescale x and y to new dimensions (new_dim x new_dim ) is from
# https://www.kaggle.com/zfturbo/facebook-v-predicting-check-ins/mad-scripts-battle/code
# by 'ZFTurbo: https://kaggle.com/zfturbo'

#########################################################################
new_dim <- 800 # new dimensions
chunks  <- 4   # for memory usage optimization (and optional multithreading)
#########################################################################

library(dplyr) 
library(readr) 
library(foreach)
#library(doSNOW)

train <- read_csv("../input/train.csv")
test <- read_csv("../input/test.csv")

train_group <- train %>%
  select(x, y, place_id) %>%
  mutate(xs = as.integer(round((x-min(x))/(max(x)-min(x)) * new_dim, digits = 0)),
         ys = as.integer(round((y-min(y))/(max(y)-min(y)) * new_dim, digits = 0))) %>%
  select(xs, ys, place_id) %>%
  group_by(xs,ys, place_id) %>% summarize(count=n())
rm(train)
  
test <- test %>% 
    mutate(xs = as.integer(round((x-min(x))/(max(x)-min(x)) * new_dim, digits = 0)),
           ys = as.integer(round((y-min(y))/(max(y)-min(y)) * new_dim, digits = 0)))
           
test_chunks <- split(test, cut(1:nrow(test), chunks))
rm(test)

#cl <- makeCluster(4, outfile="")
#registerDoSNOW(cl)

result <- foreach(chunk=1:chunks, .combine="rbind", .packages = "dplyr") %do% 
{
  test_chunk <- test_chunks[[chunk]]
  
  test_train_join <- left_join(select(test_chunk, row_id, xs, ys),
                               train_group,
                               by = c("xs", "ys"))
  
  test_train_join <- test_train_join %>% arrange(row_id, desc(count))

  result_new <- test_train_join %>% 
    group_by(row_id) %>%
    summarize(place_id=paste(head(place_id, 3),collapse=" "))

}
#stopCluster(cl)

result$place_id[result$place_id=="NA"] <- ""
write_csv(result, "result.csv")
