2016-08-22 3 views
-1

Я работаю над файлом pretty simple problem на HackerRank в течение нескольких дней, но я застрял в проблемах с тайм-аутом, и я не могу больше оптимизировать свой код.«Поиск сетки» на HackerRank с языком R

Проблема заключается в следующем: Учитывая двумерный массив цифр (размеры R * C), попробуйте найти возникновение данного двумерного шаблона цифр (размеры r * c).

Здесь вы воспроизводимый пример переменных:

pattern <- c("11111", "11111", "11110") 
text <- c("111111111111111", 
"111111111111111", 
"111111011111111", 
"111111111111111", 
"111111111111111") 
R <- 5 
C <- 15 
r <- 3 
c <- 5 

Это своего рода регулярного выражения проблемы, но в 2D, и это то, что я не мог найти где-нибудь в качестве функции готовых к употреблению в R. Есть несколько угловых случаев, с которыми мне удалось справиться, пытаясь избежать опции грубой силы (вышеприведенная версия является одним из тех случаев, когда обычное «регулярное выражение» с трудом удается найти шаблон) ,

Ниже приведен мой код: он отлично подходит для 13 из 15 случаев, но он не работает по причине таймаута, когда он идет против некоторых тестов с (например, R * C = 500 * 500 и r * c = 236 * 208.

RW <- c() 
    pattern2 <- paste0(pattern, collapse = "") 
    RW <- c(rep(NA,(C-c+1)*(R-r+1))) 
    for (v in 1:(C-c+1)) 
    { 
     for (y in 1:(R-r+1)) 
     { 
     RW[(C-c+1)*(y-1)+v] <- paste0(substr(text[y:(y+r-1)],v,c+v-1),collapse="") 
     } 
    } 
    per <- ifelse(pattern %in% RW, result <- "YES",result <- "NO") 
    cat(result, "\n") 

Пожалуйста, обратите внимание, что есть до 5 случаев для каждого теста, и это является причиной, почему мой код не: в то время как она могла бы работать ломать тест на 5 частей, он проходит порог времени, когда случаи вместе с большими R C и r c размеры.

Есть ли у кого-нибудь идеи о том, как улучшить производительность кода?

+0

Отступа вашего 'for' петеля одно улучшения. – nrussell

+0

Удален отступ, потому что SO явно не любит код с более чем 4-мя пробелами в отступе. Теперь у вас есть что-нибудь о производительности моего кода? :) – MaZe

+1

С первого взгляда ваш результат по одному элементу за один раз является классическим «убийцей производительности» в R: 'RW [length (RW) +1] <- [...]'. Вы должны инициализировать 'RW' до правильной длины перед рукой. Не связанный с производительностью, присвоение переменной 'ifelse' просто не является хорошим шагом. – nrussell

ответ

1

Если вы хотите сохранить свой подход, моим первым предложением было бы преобразовать строки в числовые матрицы, потому что substr, вероятно, не очень быстро.

Вы также можете использовать более сложные алгоритмы согласования, которые сдвигают положение более чем на одно место, например, Knuth-Morris-Pratt Algorithm.

Однако петли for всегда будут довольно медленными в R, поэтому я считаю, что лучший подход в этой ситуации действительно будет регулярным выражением. Если вы объединяете строки большой сетки в одну длинную строку, число символов между строками шаблона фиксировано. Это означает, что вы можете сделать что-то вроде этого (который, я считаю, решающий тест, вы дали):

grepl(
    paste0(pattern[1], ".{", C - c, ",}", 
      pattern[2], ".{", C - c, "}", 
      pattern[3]), 
    paste0(text, collapse = "") 
    ) 

https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

+0

Это довольно замечательно и действительно использует силу регулярного выражения, поскольку я не смог реализовать. Я думал об этом, но я даже не пытался использовать свою идею, поскольку я хотел продолжать идти своим путем. Тем не менее, теперь я должен найти способ индексировать элементы шаблона, которые будут вставлены вместе ... но спасибо, я попробую и дам вам знать! – MaZe

+0

Я только что обнаружил, что «grepl» имеет важное ограничение, которое мешает мне использовать его в моих случаях: когда значения «C - c» превышают 255, функция выдает ошибку. Это то, что я нашел в справке R: _Long регулярные выражения могут быть или не могут быть приняты: для стандарта POSIX требуется только 256 байт. Я думаю, что я должен найти другой способ, но я снова застрял: Алгоритм KMP кажется (на первый взгляд) еще медленнее в моем 500 * 500 текстах с шаблоном 236 * 208 ... – MaZe

+0

В этом случае вы можете искать (например, с grep) для каждой строки шаблона в каждой строке сетки. Таким образом вы получаете (надеюсь, небольшое количество) «строк кандидатов», которые затем можно проверить с помощью грубой силы. – AEF

 Смежные вопросы

  • Нет связанных вопросов^_^