
time_s <- as.numeric(Sys.time())

library(mxnet)
library(h2o)
paste0(installed.packages()[,"Package"], "-", installed.packages()[,"Version"])
stop()

## libs
library(data.table)
library(Metrics)
library(FNN)
library(parallel)


## read data
require(bit64)
train_dt <- fread("../input/train.csv")
test_dt <- fread("../input/test.csv")

## sampling
sample_size = nrow(train_dt)* 0.1
data_sample_indices <- 1:sample_size
data_sample <- train_dt[data_sample_indices,.(x,y)]
target_sample <- train_dt[data_sample_indices]$place_id

## rounding down x,y to decrease location inaccuracy
data_sample$x <- round(data_sample$x,2)
data_sample$y <- round(data_sample$y,2)


## functions
getTop3NNPlaces <- function(data,places)
{
  if ( nrow(data) != length(places)) 
  {
    print("Data and Target length mismatch")
    return (0)
  }
  
  knn_model <- get.knn(data, k=3)
  

  knn_indexes <- knn_model$nn.index
  
  # get top 3 places for each observation 
  knn_labels_1 <- places[knn_indexes[,1]]
  knn_labels_2 <- places[knn_indexes[,2]]
  knn_labels_3 <- places[knn_indexes[,3]]
  pred_list <- cbind(knn_labels_1,knn_labels_2,knn_labels_3)
  pred_list
}


train_pred_list <- getTop3NNPlaces(data_sample,target_sample)


print(paste("Train Sample Score:",mapk(3,as.list(target_sample), apply(train_pred_list,1,as.list) )))



### test prediction

## rounding down x,y to decrease location inaccuracy
test_dt$x <- round(test_dt$x,2)
test_dt$y <- round(test_dt$y,2)

knn_model <- get.knnx(train_dt[,.(x,y)],test_dt[,.(x,y)], k=3)


knn_indexes <-as.numeric(knn_model$nn.index)

## fast index to label conversion
place_ids_for_each_index <- train_dt[knn_indexes,]$place_id

pred_list_num <- place_ids_for_each_index
dim(pred_list_num) <- c(nrow(test_dt), 3)

final_pred_list <- apply(pred_list_num,1,function(x){paste(as.character.integer64(x),collapse=" ")})
##


submission_df <- data.frame(row_id=test_dt$row_id, place_id=final_pred_list)

sub_file_name <- "getting-started.csv"
write.csv(submission_df, sub_file_name, quote = F, row.names = F)


print(paste("Exec time:",(as.numeric(Sys.time())-time_s)/60))
