Задачка на сообразительность
Написать функции для поиска подстроки в строке (аналог String.prototype.indexOf) и разделения строки на массив по разделителю (аналог String.prototype.split). Встроенные функции использовать запрещено, за исключением String.prototype.charAt. Использовать только один цикл.
|
А сами Вы уже не можете? Вон и звание у Вас - Профессор.
|
Могу. Только какой смысл сразу выкладывать всё.
|
а в чем смысл-то?
это задачи не на сообразительность |
Это задачи первого курса специализированного факультета.
|
О да, умные люди из интернета опять меня сделали. Мешок вам на голову и в гараж.
Интересно получается: я выкладываю задачу, дебил не может её решить, говорит мне, что это я дебил и в итоге я и правда с точки зрения остальных выгляжу дебилом. Обратите внимание, что я никого конкретно не назвал дебилом, так что не сочтите за грубость. P. S. я уже неделю не пью рисперидон! |
Это типовая задача для студента-прикладника. Здесь нет и намека на задачу на сообразительность.
|
Повторю свою вторую любимую цитату (конечно, после гаражей и мешка на голове).
Это просто слова. Я тоже могу говорить слова. А вы сделайте что-нибудь. |
Задачки то конечно не на сообразительность, а на лёгкий экзамен. Быстренько состряпал, возможно что-то не учёл, но результаты не отличаются от стандартных функций:
function TestSplit(string, sep) { var words = [], word = '', char = ''; string = string + sep; for (i = 0; i < string.length; i++) { char = string.charAt(i); if (char == sep) { words.push(word); word = ''; } else { word += char; } } return words; } alert((TestSplit('1 2 3 4 5', ' ')).join(' - ')); // мой вариант alert(('1 2 3 4 5'.split(' ')).join(' - ')); // стандартный вариант function TestIndexOf(string, s) { var char = ''; for (i = 0; i < string.length; i++) { char = string.charAt(i); if (char == s) { return i; } } } alert(TestIndexOf('1 2 3 4 5', '4')); // мой вариант alert('1 2 3 4 5'.indexOf('4')); // стандартный вариант |
Vulkan,
параметры sep и s могут быть произвольной длины. |
Vulkan
Вот как, например, должна выглядеть вторая функция: 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; }; К своему стыду могу сказать, что эта задача потребовала от меня много усилий, это наверно из-за рисперидона. Оставляю Вам возможность решить первую задачу и вернуть звание дурачка обратно мне. |
Зачем все так усложнять? ;)
String.prototype.sepa = function(str, sep) { return this.replace(new RegExp(str, 'g'), sep); }; alert('1 2 3 4 5'.sepa(' ', '-')); Цитата:
String.prototype.index = function(str) { return [this].join().search(str); }; alert('1 2 3 4 5'.index('4')); |
Цитата:
Цитата:
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 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') ) |
monolithed
Цитата:
Всё ведь работает. |
По поводу своих вариантов - и правда забыл что в качестве параметров могут ещё и строки из нескольких символов передаваться, как время будет исправлю.
Matre, результаты работы твоей функции отличаются от результатов работы встроенной. |
Цитата:
|
Цитата:
Цитата:
|
Это.
|
Какой-то чудной у Вас браузер.
|
Вариант...
String.prototype.index = function (b) { for (var a = -1, d = this.length, c = 0; c < d; c++) { if (b.length > d) break; a++; a = b.charAt(a) === this.charAt(c) ? a : b.charAt(0) === this.charAt(c) ? 0 : -1; if (a == b.length - 1) return c - b.length + 1 } return a }; 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') ) |
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')); |
рони,
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), маловероятно, что существует алгоритм, позволяющий "с места", без подготовки найти заданную подстроку в строке за один просмотр исходной строки. |
Цитата:
Работает за линию от входных данных. Но условие задачи было не обеспечить определенную сложность алгоритма, а использовать только один цикл. Сделать из группы вложенных циклов, или из группы подряд идущих циклов, один единственный - вполне решаемая задача, хотя и из разряда "никогда так не делай" |
Я бы реализовал вот так:
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') ); |
Ещё вариант ...
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') ) |
Sweet, можно только один цикл использовать.
|
Цитата:
|
Цитата:
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') );не рассматриваем. |
Эта задача не требует хаков, или дополнительных циклов. Задача действительно решается в один цикл. Не надо городить огород:
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 соответствующими проверочными условиями, чтобы позиция начала поиска не выходила за пределы строки. Но это не существенно. |
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') ); Кто еще верит, что все так просто? |
B@rmaley.e><e,
Верно подмечено. (-: |
Цитата:
Это явный бред! Или может здесь кто-то панически боится циклов и микробов? Цитата:
|
Sweet, переделай в своём варианте второй цикл например под рекурсию и он будет соответствовать всем условиям =))
|
Sweet, таково условие - один цикл.
Vulkan, это все ерунда. Под одним циклом подразумевалась сложность O(n) (простой цикл по всем элементам строки). А поиск лазеек и дыр в правилах оставим юристам. |
Ой, извините! Я думал про один цикл - это не изначальное условие.
Впрочем, есть не один способ перебора без цикла, например, вот (внизу). Или вот, например: String.prototype.index = function(x){ var string = this, l1 = this.length, l2 = x.length; for(var i = 0; i < l1; i++) if(this[i] === x[0] && (function(){ var count = 0; return (function(){ if( count === l2 ) return true; if( string[i + count] === x[count++] ) return arguments.callee(); return false; })(); }())) return i; return -1; }; |
Sweet,
Цитата:
|
Продолжаю утверждать, что это простой алгоритм, который не требует особых хаков в стиле JS и который решается одним циклом.
Пусть даны СТРОКА1 и СТРОКА2. Найти позицию вхождения СТРОКА2 в СТРОКА1 Выполните цикл не более чем i < (длина СТРОКА1 - (длина СТРОКА2 / 2)) Сравнивайте начальный (0) и конечный символы (длина СТРОКА2 - 1) из СТРОКА2 с текущими позициями в СТРОКА1 (i) и (i + длина СТРОКА2 - 1), соответственно. Повторяйте сравнение. |
Т.к. теоретически точка начала совпадений мот быть в любой(каждой) позиции простым циклом нельзя(без встроенных функций[любых]).
Мой вариант: String.prototype.at = function(str) { var tl = this.length, sl = str.length; if(tl >= sl) { for(var i=0, j=0; i<tl; i++) { if(this[i] == str[j]) { ++j; if(sl == j) {return ++i-j;} } else{ if(this[i] == str[0]) {j=1;} else {i-=j; j=0;} } } return -1; } else { return -1; } } var s1 = 'aababababaO_o', l1 = 'ababaO', l2 = 'abac', l3 = 'aa', l4 = 'O_o'; alert( [ [s1.at(l1), s1.indexOf(l1)], [s1.at(l2), s1.indexOf(l2)], [s1.at(l3), s1.indexOf(l3)], [s1.at(l4), s1.indexOf(l4)] ].join('\n') ); |
Цитата:
|
Цитата:
|
Часовой пояс GMT +3, время: 11:07. |