Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 20.02.2011, 14:36
Профессор
Отправить личное сообщение для with-love-from-siberia Посмотреть профиль Найти все сообщения от with-love-from-siberia
 
Регистрация: 14.12.2009
Сообщений: 155

Matre,
Дело не в браузерах, дело в алгоритме. Он работает неверно. Проверьте на любых примерах. Например:
String.prototype.index = function (str) {
	var j = -1, c = false, L1 = this.length, L2 = str.length - 1;
	for (var i = 0; i < L1; i++) {
		if (str.charAt(0) === this.charAt(i))
			c = true, j = i;
		if (c && i === j + L2)
			return j;
		if (c && str.charAt(i) != this.charAt(i + j))
			c = false;
	}
	return j;
};

// Где ищем
var s = 'A';
// Что ищем
var t = 'AB';

alert([
	'В строке "' + s + '"', 
	'ищем "' + t + '"', 
	'и находим: ' + s.index(t), // Должно быть -1, показывает 0
	'хотя там быть не должно: ' + s.indexOf(t) // Показывает -1
].join('\n'));
Ответить с цитированием
  #22 (permalink)  
Старый 20.02.2011, 14:56
Аватар для B@rmaley.e><e
⊞ Развернуть
Отправить личное сообщение для B@rmaley.e><e Посмотреть профиль Найти все сообщения от B@rmaley.e><e
 
Регистрация: 11.01.2010
Сообщений: 1,810

рони,
String.prototype.index = function (c) {
    for (var a = -1, d = this.length, b = 0; b < d; b++) {
        if(c.length > d) return a;
        a++;
        a = c.charAt(a) === this.charAt(b) ? a : c.charAt(0) === this.charAt(b) ? 0 : -1;
        if (a == c.length - 1) return b - c.length + 1
    }
    return a
};
var s1 = 'aababaO_o',
     l1 = 'abaO', l2 = 'abac', l3 = 'aa', l4 = 'O_o';
alert( [
 [s1.index(l1), s1.indexOf(l1)]
].join('\n') )


Matre, вполне нормальный. Причем точно такие же результаты будут у других пользователей.
А вот алгоритм у Вас кривой.

Принимая во внимание то, что все известные алгоритмы поиска подстроки требуют либо предварительной обработки данных, либо работают дольше, чем за O(n), маловероятно, что существует алгоритм, позволяющий "с места", без подготовки найти заданную подстроку в строке за один просмотр исходной строки.
Ответить с цитированием
  #23 (permalink)  
Старый 20.02.2011, 15:19
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

Сообщение от B@rmaley.e><e
Принимая во внимание то, что все известные алгоритмы поиска подстроки требуют либо предварительной обработки данных, либо работают дольше, чем за O(n), маловероятно, что существует алгоритм, позволяющий "с места", без подготовки найти заданную подстроку в строке за один просмотр исходной строки.
http://algolist.manual.ru/search/esearch/kmp.php
Работает за линию от входных данных.
Но условие задачи было не обеспечить определенную сложность алгоритма, а использовать только один цикл.
Сделать из группы вложенных циклов, или из группы подряд идущих циклов, один единственный - вполне решаемая задача, хотя и из разряда "никогда так не делай"
Ответить с цитированием
  #24 (permalink)  
Старый 20.02.2011, 15:48
Профессор
Отправить личное сообщение для Sweet Посмотреть профиль Найти все сообщения от Sweet
 
Регистрация: 16.03.2010
Сообщений: 1,618

Я бы реализовал вот так:
String.prototype.index = function(x){
  var i1, i2, l1 = this.length, l2 = x.length;

  for(i1 = 0; i1 < l1; i1++)
    if(this[i1] === x[0])
      for(i2 = 0; i2 <= l2; i2++){
        if(i2 === l2) return i1;
        if(this[i1 + i2] === x[i2]) continue;
        break;
      };
  return -1;
};

var s1 = 'aababaO_o', 
    l1 = 'abaO', l2 = 'abac', l3 = 'aa', l4 = 'O_o'; 
alert( [ 
  [s1.index(l1), s1.indexOf(l1)],
  [s1.index(l2), s1.indexOf(l2)],
  [s1.index(l3), s1.indexOf(l3)],
  [s1.index(l4), s1.indexOf(l4)] 
].join('\n') );
Ответить с цитированием
  #25 (permalink)  
Старый 20.02.2011, 16:11
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,123

Ещё вариант ...
String.prototype.index = function (c) {
    for (var a = -1, d = this.length, b = 0; b < d; b++) {
        if (c.length > d) break;
        a++;
        if (c.charAt(a) !== this.charAt(b)) {
            b -= a;
            a = -1
        }
        if (a == c.length - 1) return b - c.length + 1
    }
    return a
};
var s1 = 'aababaO_o',
     l1 = 'abaO', l2 = 'abac', l3 = 'aa', l4 = 'O_o';
alert( [
 [s1.index(l1), s1.indexOf(l1)]
].join('\n') )

// Где ищем
var s = 'A';
// Что ищем
var t = 'AB';

alert([
	'В строке "' + s + '"',
	'ищем "' + t + '"',
	'и находим: ' + s.index(t), // Должно быть -1, показывает 0
	'хотя там быть не должно: ' + s.indexOf(t) // Показывает -1
].join('\n'));

var s1 = 'aababaO_o',
     l1 = 'aba', l2 = 'abac', l3 = 'aa', l4 = 'O_o';

alert( [
 [s1.index(l1), s1.indexOf(l1)],
 [s1.index(l2), s1.indexOf(l2)],
 [s1.index(l3), s1.indexOf(l3)],
 [s1.index(l4), s1.indexOf(l4)]
].join('\n') )
Ответить с цитированием
  #26 (permalink)  
Старый 20.02.2011, 16:18
Аватар для Vulkan
Профессор
Отправить личное сообщение для Vulkan Посмотреть профиль Найти все сообщения от Vulkan
 
Регистрация: 25.05.2010
Сообщений: 511

Sweet, можно только один цикл использовать.
Ответить с цитированием
  #27 (permalink)  
Старый 20.02.2011, 16:25
Профессор
Отправить личное сообщение для Sweet Посмотреть профиль Найти все сообщения от Sweet
 
Регистрация: 16.03.2010
Сообщений: 1,618

Сообщение от Vulkan
можно только один цикл использовать.
А мне захотелось использовать два! Хотя, конечно, можно еще было бы вместо for воспользоваться while, или вообще без циклов...
Ответить с цитированием
  #28 (permalink)  
Старый 20.02.2011, 16:27
Аватар для B@rmaley.e><e
⊞ Развернуть
Отправить личное сообщение для B@rmaley.e><e Посмотреть профиль Найти все сообщения от B@rmaley.e><e
 
Регистрация: 11.01.2010
Сообщений: 1,810

Сообщение от Gvozd
Сделать из группы вложенных циклов, или из группы подряд идущих циклов, один единственный - вполне решаемая задача
Как Вы собрались объединять, например, это?
var arr = [3,4,5,6,7,8,9,0,1 /* and so on */], s = 0;
for(var i =0, length = arr.length; i < length; ++i){ // предварительные вычисления
  s += arr[i];
}

for(var i = 0, length = arr.length; i < length; ++i){ // самое то.
  arr[i] = (arr[i] / s * 100).toFixed(2) + '%';
}
alert([s, arr].join('\n'));

Сомневаюсь, что КМП можно записать одним циклом.

P.S. Грязные "хаки" вида
function indexOf(haystack, needle){
  var n = haystack.length,
       m = needle.length;
  var i = 0, j = 0, offset = 0;
  for(var k = 0, length = n * m; k < length; ++k){
    i = k / m | 0;
    j = k % m;
    if(haystack[i + offset] != needle[j]){
      offset = 0;
      k += m - j - 1;
    } else {
      ++offset;
      if(j == m - 1) return i;
    }
  }
  return -1;
}

var s1 = 'aababaO_o',  
    l1 = 'abaO', l2 = 'abac', l3 = 'aa', l4 = 'O_o';  
alert( [  
  [indexOf(s1, l1), s1.indexOf(l1)],
  [indexOf(s1, l2), s1.indexOf(l2)],
  [indexOf(s1, l3), s1.indexOf(l3)],
  [indexOf(s1, l4), s1.indexOf(l4)],
  [indexOf(s1, 'a'), s1.indexOf('a')]
].join('\n') );
не рассматриваем.
Ответить с цитированием
  #29 (permalink)  
Старый 20.02.2011, 17:02
Профессор
Отправить личное сообщение для with-love-from-siberia Посмотреть профиль Найти все сообщения от with-love-from-siberia
 
Регистрация: 14.12.2009
Сообщений: 155

Эта задача не требует хаков, или дополнительных циклов. Задача действительно решается в один цикл. Не надо городить огород:
String.prototype.hasAt = function(needle, pos)
{
	var i = Math.min(this.length, Math.max(0, Number(pos) || 0));
	var j;
	var found;
	for ( ; i < this.length; i++) {
		if ( found ) {
			if ( i - j == needle.length ) {
				return j;
			}
			found = this.charAt(i) == needle.charAt(i - j);
		} else {
			found = this.charAt(i) == needle.charAt(0);
			if ( found ) {
				j = i;
			}
		}
	}
	return found && this.length - j == needle.length 
		? j 
		: -1;
};

Для "чистоты" эксперимента следовало бы заменить Math.min/Math.max соответствующими проверочными условиями, чтобы позиция начала поиска не выходила за пределы строки. Но это не существенно.

Последний раз редактировалось with-love-from-siberia, 20.02.2011 в 17:04.
Ответить с цитированием
  #30 (permalink)  
Старый 20.02.2011, 17:34
Аватар для B@rmaley.e><e
⊞ Развернуть
Отправить личное сообщение для B@rmaley.e><e Посмотреть профиль Найти все сообщения от B@rmaley.e><e
 
Регистрация: 11.01.2010
Сообщений: 1,810

String.prototype.hasAt = function(needle, pos)
{
	var i = Math.min(this.length, Math.max(0, Number(pos) || 0));
	var j;
	var found;
	for ( ; i < this.length; i++) {
		if ( found ) {
			if ( i - j == needle.length ) {
				return j;
			}
			found = this.charAt(i) == needle.charAt(i - j);
		} else {
			found = this.charAt(i) == needle.charAt(0);
			if ( found ) {
				j = i;
			}
		}
	}
	return found && this.length - j == needle.length 
		? j 
		: -1;
};

var s1 = 'aababababaO_o',   
    l1 = 'ababaO';   
alert( [
  [s1.hasAt(l1), s1.indexOf(l1)] 
].join('\n') );


Кто еще верит, что все так просто?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Задачка на смекалку subzey Общие вопросы Javascript 52 16.08.2013 21:39
задачка по геометрии js lammeR Общие вопросы Javascript 16 02.02.2011 16:01
Небольшая задачка Maksim jQuery 4 30.09.2009 19:43
задачка на подумать x-yuri Оффтопик 16 11.06.2009 12:39
Задачка: вывод div по ссылке alt5000 Элементы интерфейса 19 28.10.2008 21:21