Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Интересное задание codewars.com (https://javascript.ru/forum/misc/73461-interesnoe-zadanie-codewars-com.html)

j0hnik 06.05.2018 14:55

Цитата:

Сообщение от Alexandroppolus
пропатчить некоторые встроенные функции.

лучше не привыкать :)

j0hnik 06.05.2018 14:56

Alexandroppolus,
какие преимущества быть в каком либо клане???

Alexandroppolus 06.05.2018 15:16

Цитата:

Сообщение от j0hnik (Сообщение 484741)
лучше не привыкать :)

в той ситуации выбора не было

Alexandroppolus 06.05.2018 15:21

Цитата:

Сообщение от j0hnik (Сообщение 484742)
Alexandroppolus,
какие преимущества быть в каком либо клане???

никаких
мне дали ссылку на этот сайт на работе, ну я и вступил, чтобы была соревновательность со знакомыми людьми, а не какими-то неизвестными персонажами (с помощью клана всех сразу видно). Потом все клановые быстро забили, я по инерции ещё немного порешал то что казалось интересным и незамороченным, и тоже забил.

сейчас, оглядываясь назад, из того что решил могу вспомнить интересных задач только штук 5-7...

j0hnik 06.05.2018 18:27

Alexandroppolus,

const solution = new RegExp('.');
var str = solution.test.toString();
solution.test = function(x) { /* тут любое решение )) */ };
solution.test.toString = function() { return str; };


как этой фишкой пользоваться?

Alexandroppolus 06.05.2018 21:41

j0hnik,
ты про задачу с делимостью на 7?

вместо /* тут любое решение )) */ написать что-то вроде

return !(parseInt(x, 2) % 7)


Тут косяк автора вот в чем: он хочет от игрока регулярку, которой проверяет строку (методом test). А мы тупо берем и заменяем этот метод своей функцией. Чтобы такое не прокатило, автор теста проверяет результат test.toString(), но мы и toString переопределили.

Самый правильный подход - получать от игрока строку. Проверять что это строка (typeof) и по ней создавать регекс. При этом предварительно сохранить метод test из RegExp.prototype, и сам конструктор RegExp, потом это всё использовать. Тогда юзер нигде ничего не перепишет и будет вынужден честно упороться и таки написать регулярку.

j0hnik 06.05.2018 21:50

Alexandroppolus,
это я написал, чтоб тестировать проще было :lol:

надеялся что мухлевать никто не будет

https://www.codewars.com/kata/regula...ain/javascript

j0hnik 04.08.2018 02:23

Интересная ката 6kyu (новичок+)
Нужно найти во входном массиве (от 1 до n) пропущенные числа и вернуть их новый массив в порядке возрастания.

[8, 10, 11, 7, 3, 15, 6, 1, 14, 5, 12] ---> [2, 4, 9, 13]

ВАЖНО[!] решение должно быть скоростным, проверка на огромных массивами, с редкими пропусками.

рони 04.08.2018 10:05

j0hnik,
<script>
function fn(b) {
    for (var c = [], a = 0; a < b.length; a++) c[b[a]] = true;
    b = [];
    for (a = 1; a < c.length; a++) c[a] || b.push(a);
    return b
};
var a =  [8, 10, 11, 7, 3, 15, 6, 1, 14, 5, 12] ;
    a = fn(a);
document.write(JSON.stringify(a, null, 4))
</script>

j0hnik 04.08.2018 10:33

рони,
Такой была моя первая попытка, только я чиcла пушил,
var x = c[b[a]];
c[x] = x;

кодварс ответил мне: "Хей! бро, не, ты меня не понял, нужно ОЧЕНЬ быстрое решение!"

Alexandroppolus 04.08.2018 10:36

N указано, или это максимальный элемент в массиве?

j0hnik 04.08.2018 10:41

Alexandroppolus,
н не указано, длинна максимальная до 30.000.000
есть метка 1 <= кол-во пропущенных <= 10
но встречалось и больше почему-то. :(

Malleys 04.08.2018 10:53

Вот так проскочило:
function missNumsFinder(arr) {
  const present = new Array(arr.length), result = [];

  for(let i = 0, { length } = arr; i < length; ) {
    present[arr[i++]] = true;
  }

  for(let i = 1, { length } = present; ; ) {
    while(i in present) i++;
    if(i >= length) break;
    result.push(i++);
  }

  return result;
}


Изначально у меня было
const present = [], result = [];
Но если там около 30000000 раз добавлять новые индексы, то массив меняет свой размер (меняются внутренние свойства, что приводит к очень долгому вычислению и изменению внутреннего состояния массива)

j0hnik 04.08.2018 11:01

Malleys,
так не проходит, до 30.000.000 там 2 теста, это решение крайне редко успевает первый выполнить.
эта ката (Hardcore version)
м.б. вы решали без этой метки?

j0hnik 04.08.2018 11:06

Malleys,
а вот, Вижу, у вас прокатило. а с какой попытки?

Malleys 04.08.2018 11:17

Когда было `const present = [], result = [];`, то всегда не хватало времени, когда поменял на `const present = new Array(arr.length), result = [];`, то через один-пару раз проходит, иногда много раз не проходит, иногда больше проходит, чем не проходит...

j0hnik 04.08.2018 11:21

Malleys,
:)

Alexandroppolus 04.08.2018 11:23

Может, попробовать Uint8Array ?

j0hnik 04.08.2018 11:31

Alexandroppolus,
есть такая тема :)

j0hnik 04.08.2018 12:21

рони,
ваше решение будет стабильно проходить если:

for (var c = Array(b.length).fill(0), a = 0; a < b.length; a++) c[b[a]] = true;

без .fill(0) борода! вот такой парадокс

j0hnik 04.08.2018 12:41

рони,
https://jsperf.com/453543534sdasad

Aetae 04.08.2018 13:32

function fn(arr){
  var obj = Object.create(null), i = arr.length, max = 0;
  while(i--){
    if(arr[i] > max){
      while(++max < arr[i])
        obj[max] = true;
    }else{
      delete obj[arr[i]];
    }
  }
  return Object.keys(obj);
}

рони 04.08.2018 15:04

Цитата:

Сообщение от j0hnik
ваше решение будет стабильно проходить

чем c = [] не устроило?

j0hnik 04.08.2018 17:16

рони,
не меня, там проверка, вот ее и не устраивало. чем не могу сказать

рони 04.08.2018 17:22

Цитата:

Сообщение от j0hnik
чем не могу сказать

видимо причина в том, что
Цитата:

Сообщение от Malleys
массив меняет свой размер (меняются внутренние свойства, что приводит к очень долгому вычислению и изменению внутреннего состояния массива)


Alexandroppolus 04.08.2018 17:24

https://javascript.ru/forum/misc/734...tml#post483544 - кто-нибудь пробовал решить? :)

рони 04.08.2018 17:38

Цитата:

Сообщение от Alexandroppolus
кто-нибудь пробовал решить?

попробую :)

рони 04.08.2018 18:48

Alexandroppolus,
не получилось.

Ermite 04.08.2018 19:58

Такое предлагал кто-нибудь?)
14 символов вместе с ;
reverse = a => a.sort(()=>1); 

console.log(reverse(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']));
console.log(reverse(['as', 'df', 'vv', 'ww', 'we']));

j0hnik 04.08.2018 20:02

Ermite,
в хроме не работает такое решение

Белый шум 04.08.2018 23:06

Цитата:

Сообщение от Alexandroppolus (Сообщение 491757)
https://javascript.ru/forum/misc/734...tml#post483544 - кто-нибудь пробовал решить? :)

function smaller(arr) {
   return arr.map(
     (cur, i) => arr.slice(i+1).reduce(
       (sum, cur1) => {
         return (cur1 < cur) ? sum+1 : sum;
       }, 0
     )
   );
}

console.log(smaller([5, 4, 3, 2, 1]), '[4, 3, 2, 1, 0]');
console.log(smaller([1, 2, 3]), '[0, 0, 0]');
console.log(smaller([1, 2, 0]), '[1, 1, 0]');
console.log(smaller([1, 2, 1]), '[0, 1, 0]');
console.log(smaller([1, 1, -1, 0, 0]), '[3, 3, 0, 0, 0]');
console.log(smaller([5, 4, 7, 9, 2, 4, 4, 5, 6]), '[4, 1, 5, 5, 0, 0, 0, 0, 0]');


Не гурман, поэтому никаких послевкусий ))

j0hnik 05.08.2018 01:02

шум, братец, не все так просто для этой каты решающий фактор скорость.
и даже без использование абстракций (что быстрей как минимум вдвое) не прокатывает =(
function smaller(arr) {
		var newArr = [], x = arr.length;
			for (var i = 0; i<x; i++){
			var s = 0;
			for(var j = i; j<x; j++){
				s = (arr[j] < arr[i]) ? s+1 : s;
			}
			newArr[i]=s;
		}
		return newArr;
	}


Alexandroppolus, тут решение наверное кардинально другое?

Aetae 05.08.2018 01:23

j0hnik, у меня мысль примерно также шала, только вместо for - обратные while - меньше буков и иногда быстрее.
Можно ещё добавить "кэш" - сохранять количество и позицию для для конкретной цифры и если таковая нашлась на следующих итерациях - не проходить весь цикл заново, а только до той позиции, прибавляя предыдущий результат и обновляя кэш. Это даст выигрыш в случае множества повторов.
Но в решении не было изюминки, слишком оно в лоб, а потому врядли требуемое, так что я плюнул.)

j0hnik 05.08.2018 01:36

Aetae,
а while это конечно копейки.
а вот кеш это идея, там массивы по 80000 - 100000 length значения -1000 - 1000

Aetae 05.08.2018 03:01

С кэшем примерно так, но как и ожидалось - не проходит:)
function smaller(arr) {
  var length = arr.length, 
      i = length, j, 
      result = new Array(length),
      cache = Object.create(null);
  while (i--){
    if(arr[i] in cache){
      j = cache[arr[i]];
      cache[arr[i]] = i;
      result[i] = result[j];
    }else{
      cache[arr[i]] = i;
      result[i] = 0;
      j = length;
    }
    while(--j > i)
      if(arr[j] < arr[i]) 
        result[i]++;
  }
  return result;
}
Нужен какой-то трюк.)

...можно ещё запоминать максимальное число и минимальное, в первом случае - просто прибавлять оставшуюся длину, во втором ставить ноль. Но это всё рост "вширь", а надо, думается в глубину.)

j0hnik 05.08.2018 03:14

Aetae,
Истина где-то рядом!
Проснется подскажет

j0hnik 05.08.2018 03:17

Цитата:

Сообщение от Aetae
Но это всё рост "вширь", а надо, думается в глубину.)

да, там как минимум еще тройной прирост нужен, это вряд ли спасет

Alexandroppolus 05.08.2018 04:03

Цитата:

Сообщение от j0hnik
тут решение наверное кардинально другое?

Разумеется, очевидный вложенный цикл не прокатит, как его не оптимизируй :)
А всё из-за квадратичной сложности. Да, асимптотика здесь рулит.

В качестве подсказки - правильное решение имеет сложность O(n*ln(n)), что на порядки быстрее при данных объёмах.

j0hnik 05.08.2018 06:25

function smaller(arr) {
	var n = arr.length, node = null, result, newArr = new Array(n);
	function addTo(node, value, smallerCount){
		if(node === null) { //старт
			node = { value: value, lowerCount: 0, count: 1, left: null, right: null }; 
			result = smallerCount;
		}
		else if(node.value === value){ // баланс 
			node.count++;
			result = smallerCount + node.lowerCount;
		}
		else if(value < node.value){ 
			node.lowerCount++;
			node.left = addTo(node.left, value, smallerCount);
			// дублирующее количество правых +1
		}
		else node.right = addTo(node.right, value, smallerCount + node.count + node.lowerCount); // количество меньших чисел
		return node;
	}
	for(var i = n-1; i >= 0; i--) {
		node = addTo(node, arr[i], 0);
		newArr[i] = result;
	}
	return newArr;
}


лучше шестерки под чаек решать, чем так загоняться :cray:

Alexandroppolus 05.08.2018 08:34

j0hnik,
Чтобы юзеры не слишком загонялись, автор задачи специально не стал добавлять более-менее отсортированные массивы, и можно обойтись обычным бинарным деревом без всяких там балансировок )

А шестерки надоедают быстро, какие-то они все однообразные.


Часовой пояс GMT +3, время: 14:47.