Check incrementation of adjacent spots in matrix, JavaScript - javascript

I've been using CodeFights for a couple days (which I highly recommend as it's a great way to build on to your skills), and today I came across a challenge that I couldn't figure out for the life of me. I hate to give away solutions, but nothing I tried would work.
Generally, the challenge was this: Given any matrix of numbers, such as
[1,4,5,8]
[2,3,6,7]
as a parameter to a function, return true if, starting in the top-left corner, you could traverse all the numbers in the array, incrementing by one each time, by moving only to adjacent spots. So, I start at 1, 2 is adjacent so I can move there, 3 is adjacent to 2 so I can move there, and so on and so forth. If you can't get through the entire matrix then return false. It seems pretty simple until you get down to it.
you must:
– Keep track and compare the number of items checked, against the number of items in the matrix.
– Somehow check each adjacent spot for the value of the current spot +1, and then make that the current spot. Then keep checking until you run out of numbers, otherwise return false.
I tried so many different ways of doing this, using 3 or 4 levels of nested for loops, and nothing I tried would work for all of the test cases. I probably wont ever see the problem again, but just for knowledge's sake, could anyone point me in the right direction? Namely just helping me to understand how to efficiently compare against adjacent spaces in a matrix (to maybe avoid giving away the answer for future CodeFighters)?
Just to clarify:
The function would be set up passing in a matrix:
function traverse(matrix) {
}
and something like this would return true:
[[ 1, 4, 5, 8]
[ 2, 3, 6, 7]]
and something like this would return false:
[[ 1, 3, 5, 8]
[ 2, 4, 9, 7]
[10,12, 6,11]]
Any help just to understand where I may have gone wrong in my execution is greatly appreciated. (Btw I can't post exactly what I tried because I don't believe there's a way to get back to it on the website.)

Related

I have an array of objects. I want to randomly output objects whose sum of values ​is equal to eight

const obj =
[
{noir: 1},
{croch: 0.5},
{doubleCroch: 1},
{triollet: 1.5},
{quatreDouble: 2}
];
desired output example:
2, 2, 0.5, 0.5, 1, 2
for (var i = 0 ; i < obj.length ; i++ ){
var randomItem = obj[Math.floor(Math.random()*obj.length )];
}
That brings me five random items. But I want to have elements whose sum of values ​​is equal to eight.
It looks like a condition inside the random
I think you have a couple options here:
1. The foolproof approach
You calculate and collect all the possible combinations that sum up to 8. Then you pick one combination at random. This might be computationally expensive, especially since you seem to allow for duplicates. Not trivial to implement.
2. The happy-go-lucky approach
You keep picking elements at random from your object as you're doing and keep track of the sum. If the sum hits 8, you have a winning combination. If it surpasses 8, you start over from scratch. A lot easier to implement, but might theoretically run infinitely.
3. The over-engineered approach
You start out the same as in the previous approach, but if the sum surpasses 8, you discard the last selected element and pick another one. This would require you to keep track of all the elements you've already tried for every picked element because you might be required to backtrack further than the last selected element. The would be the hardest to implement.

Levenshtein distance for search field with includes

Assume I have the following array:
const data = [{
label: 'Östra Halmgatan, Stockholm',
value: 'Östra Halmgatan, Stockholm'
},
{
label: 'Västra Vägen, Stockholm',
value: 'Västra Vägen, Stockholm'
},
{
label: 'Cykelvägen, Göteborg',
value: 'Cykelvägen, Göteborg'
},
{
label: 'Servicevägen, Köpenhamn',
value: 'Servicevägen, Köpenhamn'
}
]}
I want to have a search where the user can search for an item with fuzzy search.
The first step I took was to implement a filter levenshtein algorithm that checks the distance. I filter out all the results with a distance above 2.
The first problem was that when the users start typing, the distance will be way off. If they write ’Serv’ it gives a distance of 19, but it should obviously show the item with Servicevägen, Köpenhamn. I fixed this by only using a substring (from 0 to userInput.length) for the labels instead. This leads to the correct functionality for most cases. So if they write Vöstra (with a typo) it will only show Östra Halmgatan, Stockholm and Västra Vägen, Stockholm (since the distance for those two would be 2 or less).
However, this leads to another issue. If someone would write Stockholm, the first two items should of course be displayed. I fixed this by adding a fix for the filter function, which also checks if the user input value is included in the label string (with all strings set to lowercase).
This works surprisingly well, but I do still have one issue I was wondering if someone can help me figure out.
If someone would be on a non-swedish keyboard for example, I would need to show Göteborg if they were to enter Goteborg. The include doesn't take into account a typo (or a distance) when using the include, only from the start.
Basically, I was wondering if there was a way to write an includes function for strings that takes into account a distance? That would solve all the use cases for my case. Then I could use that function only since Vöstra would return true for the first two (given that the distance is set to 2 or lower). It would also work for Goteborg and Stockholm.
What I'm thinking is you write a function in the style of
String.prototype.includesWithDistance(value: string, maxDistance: number) {
//... how would you approach this?
return substring (with a distance) is included
}
I see a lot of possible cases where this could be used so any ideas are appreciated.
You might want to try out Smith-Waterman Gotoh or Jaro-Winkler algorithm for this kind of calculation. It is more precise and capable of handling typo.
You can test your comparison here:
Test Similarity

Logic to find the nearest possible sum of array values to target

This is a simpler version of knapsack, which I am having trouble wrapping my head around.
In my version I don't care how valuable the items are. I just want to get as close to the weight capacity as possible, and order doesn't matter because I'm doing it multiple times and shuffling in between.
So to be clear:
I have an array of values like: weights = [{44, 52, 100, 33, 33, 22, 25, 4, 6, 77, 88, 45}] and a capacity of, for example:capacity: 204
I want the closest combination of array values to that capacity number without repeating any, I'm not super great at math, and the wikipedia article has completely lost me.
Can someone explain how to get this?
Naive approach: cycle through all subsets of N numbers, and check the sum of weights. Running time is O(2^N*N)
You can try dynamic programming.
The problem can be divided into 2 subproblems, to check whether the sum of set is equal to or less than the capacity.
1) Include the current element in subset, and recur for the remaining items with remaining sum.
2) Exclude the current element from the subset, recur remaining items.
The base case of the recursion would be when no items are left. Finally, we output the items included in the subset.
Running time is O(n*capacity) in O(n)

Partitioning an array into 3 columns with JS

Given an unknown array of integers of an unknown length, whose values are also unknown, how can I organize them into three columns, so that the sum of the left most group is the largest, the middle the second largest and the third is the smallest with the groups being as close as possible in size.
The actual goal here is to organize <ul> elements by their size (# of <li> elements they contain) into three columns. I'm looking for an answer in javascript, but if someone can explain the logic simply enough that would good enough :)
So in other words given an array such as...
var set = [1, 1, 4, 6, 7, 10, 3, 6]
Would be organized as...
var left = [10, 4]
var middle = [6, 7]
var right = [3, 6, 1, 1]
There are other possibilities. The first column sums to 14, but this could be the outcome of various combinations such as [6, 4, 3, 1]. Being organized in such a way would make it difficult to get the right values for the next column, so preferably use the largest numbers earlier on, as in my example above. *
I'm sure this has been asked and answered before but I didn't know how to look this up. I did some research and found out that this is pretty much the Partitioning Problem, although I'm still at a loss on how to do it or if there is simple one feasible answer here. Anything that works for the simple example I gave should suffice.
* EDIT: On second thought, this may be an incorrect assumption.

How can I reliably subsort arrays using DOM methods?

UP-FRONT NOTE: I am not using jQuery or another library here because I want to understand what I’ve written and why it works (or doesn’t), so please don’t answer this with libraries or plugins for libraries. I have nothing against libraries, but for this project they’re inimical to my programming goals.
That said…
Over at http://meyerweb.com/eric/css/colors/ I added some column sorting using DOM functions I wrote myself. The problem is that while it works great for, say, the simple case of alphabetizing strings, the results are inconsistent across browsers when I try to sort on multiple numeric terms—in effect, when I try to do a sort with two subsorts.
For example, if you click “Decimal RGB” a few times in Safari or Firefox on OS X, you get the results I intended. Do the same in Chrome or Opera (again, OS X) and you get very different results. Yes, Safari and Chrome diverge here.
Here’s a snippet of the JS I’m using for the RGB sort:
sorter.sort(function(a,b){
return a.blue - b.blue;
});
sorter.sort(function(a,b){
return a.green - b.green;
});
sorter.sort(function(a,b){
return a.red - b.red;
});
(sorter being the array I’m trying to sort.)
The sort is done in the tradition of another StackOverflow question “How does one sort a multi dimensional array by multiple columns in JavaScript?” and its top answer. Yet the results are not what I expected in two of the four browsers I initially tried out.
I sort (ha!) of get that this has to do with array sorts being “unstable”—no argument here!—but what I don’t know is how to overcome it in a consistent, reliable manner. I could really use some help both understanding the problem and seeing the solution, or at least a generic description of the solution.
I realize there are probably six million ways to optimize the rest of the JS (yes, I used a global). I’m still a JS novice and trying to correct that through practice. Right now, it’s array sorting that’s got me confused, and I could use some help with that piece of the script before moving on to cleaning up the code elsewhere. Thanks in advance!
UPDATE
In addition to the great explanations and suggestions below, I got a line on an even more compact solution:
function rgbSort(a,b) {
return (a.red - b.red || a.green - b.green || a.blue - b.blue);
}
Even though I don’t quite understand it yet, I think I’m beginning to grasp its outlines and it’s what I’m using now. Thanks to everyone for your help!
OK. So, as you've discovered, your problem is that the default JavaScript sort is not guaranteed to be stable. Specifically, I think that in your mind it works like this: I'll sort by blueness, and then when I sort by greenness the sorter will just move entries in my array up and down but keep them ordered by blueness. Sadly, the universe is not so conveniently arranged; the built-in JS sort is allowed to do the sort how it likes. In particular, it's allowed to just throw the contents of the array into a big bucket and then pull them out sorted by what you asked for, completely ignoring how it was arranged before, and it looks like at least some browsers do precisely that.
There are a couple of ways around this, for your particular example. Firstly, you could still do the sort in three separate calls, but make sure those calls do the sort stably: this would mean that after sorting by blueness, you'd stably sort by greenness and that would give you an array sorted by greenness and in blueness order within that (i.e., precisely what you're looking for). My sorttable library does this by implementing a "shaker sort" or "cocktail sort" method (http://en.wikipedia.org/wiki/Cocktail_sort); essentially, this style of sorting walks through the list a lot and moves items up and down. (In particular, what it does not do is just throw all the list items into a bucket and pull them back out in order.) There's a nice little graphic on the Wikipedia article. This means that "subsorts" stay sorted -- i.e., that the sort is stable, and that will give you what you want.
However, for this use case, I wouldn't worry about doing the sort in three different calls and ensuring that they're stable and all that; instead, I'd do all the sorting in one go. We can think of an rgb colour indicator (255, 192, 80) as actually being a big number in some strange base: to avoid too much math, imagine it's in base 1000 (if that phrase makes no sense, ignore it; just think of this as converting the whole rgb attribute into one number encompassing all of it, a bit like how CSS computes precedences in the cascade). So that number could be thought of as actually 255,192,080. If you compute this number for each of your rows and then sort by this number, it'll all work out, and you'll only have to do the sort once: so instead of doing three sorts, you could do one: sorter.sort(function(a,b) { return (a.red*1000000 + a.green*1000 + a.blue) - (b.red*1000000 + b.green*1000 + b.blue) } and it'll all work out.
Technically, this is slightly inefficient, because you have to compute that "base 1000 number" every time that your sort function is called, which may be (is very likely to be) more than once per row. If that's a big problem (which you can work out by benchmarking it), then you can use a Schwartzian transform (sorry for all the buzzwords here): basically, you work out the base-1000-number for each row once, put them all in a list, sort the list, and then go through the sorted list. So, create a list which looks like [ [255192080, <table row 1>], [255255255, <table row 2>], [192000000, <table row 3>] ], sort that list (with a function like mylist.sort(function(a,b) { return a[0]-b[0]; })), and then walk through that list and appendChild each of the s onto the table, which will sort the whole table in order. You probably don't need this last paragraph for the table you've got, but it may be useful and it certainly doesn't hurt to know about this trick, which sorttable.js also uses.
I would approach this problem in a different manner. It appears you're trying to reconstruct all the data by extracting it from the markup, which can be a perilous task; a more straightforward approach would be to represent all the data you want to render out to the page in a format your programs can understand from the start, and then simply regenerate the markup first on page load and then on each subsequent sort.
For instance:
var colorsData = [
{
keyword: 'mediumspringgreen',
decimalrgb: {
r: 0,
g: 250,
b: 154
},
percentrgb: {
r: 0,
g: 98,
b: 60.4
},
hsl: {
h: 157,
s: 100,
l: 49
}
hex: '00FA9A',
shorthex: undefined
},
{
//next color...
}
];
That way, you can run sorts on this array in whatever way you'd like, and you're not trying to rip data out from markup and split it and reassign it and all that.
But really, it seems you're maybe hung up on the sort functions. Running multiple sorts one after the other will get unintended results; you have to run a single sort function that compares the next 'column' in the case the previous one is found to be equal. An RGB sort could look like:
var decimalRgbForwards = function(a,b) {
var a = a.decimalrgb,
b = b.decimalrgb;
if ( a.r === b.r ) {
if ( a.g === b.g ) {
return a.b - b.b;
} else {
return a.g - b.g;
}
} else {
return a.r - b.r;
}
};
So two colors with matching r and g values would return for equality on the b value, which is just what you're looking for.
Then, you can apply the sort:
colorsData.sort(decimalRgbForwards);
..and finally iterate through that array to rebuild the markup inside the table.
Hope it helps, sir-

Categories