Reputation: 8233
I have a question, it can be very simple for you, but I don't know how to do it with a simple and a powerful solution.
So, let's consider we have a rectangle of numbers like that :
154784587
251436258
748541254
965874584
521414174
How can I crawl it to find horizontally or vertically multiples of 3 (e.g.) ? I thought about converting it to a 2 dimensions array :
var arr = [
[1,5,4,7,8,4,5,8,7],
...
]
And then double loop into it (horizontal and vertical). But that sounds messy, do you know how I could achieve that in a clean and simple way ?
Upvotes: 0
Views: 45
Reputation: 3254
Based on your comments, this is what I understand:
I assumed that the input value would be a string and that map
, reduce
, and filter
methods were available.
var stream = "154784587251436258748541254965874584521414174";
var columns = 9;
Three helpers were required:
Some of these functions look very simple, but were done to enhance the readability of the code:
function groupChars(stringValue, numberOfCharacters) {
var regex = new RegExp(".{1," + numberOfCharacters + "}", "g");
return stringValue.match(regex);
}
function getNthCharacter(stringValue, index) {
return stringValue[index];
}
function isDivisibleBy(divisor) {
return function(value) {
return value % divisor === 0;
}
}
function getValuesDivisibleBy(stringValues, divisor) {
return stringValues.map(function(item) {
return parseInt(item, 10);
}).filter(isDivisibleBy(3));
}
Using these helpers, row (or horizontal) data was captured by grouping characters together by the number of columns. Given a set of rows, the column (or vertical) data could then be extracted.
function getRowData(stream, columns) {
return groupChars(stream, columns);
}
function getColumnData(rowData, columns) {
var columnData = [];
for (var i = 0; i < columns; i++) {
columnData.push(rowData.map(function(row) {
return row[i]
}).join(''));
}
return columnData;
}
Values were then extracted from the stream by first extracting the rows and then extracting the columns. This produced an array of strings that represent the row and columns values.
function getBoxedData(stream, columns) {
var data = {};
data.rows = getRowData(stream, columns);
data.columns = getColumnData(data.rows, columns);
return data.rows.concat(data.columns);
}
The final processing was done by taking each string and parsing it for numbers or groups of numbers based on the number of columns. A loop was required to group the values as single digit, double digit, and up to n-digit values. Each value was parsed as an integer and then verified for it's divisibility by 3.
var set = getBoxedData(stream, columns);
var results = set.reduce(function(result, item) {
for(var i = 0; i < item.length;) {
var values = groupChars(item, ++i);
var valuesByDivisibleThree = getValuesDivisibleBy(values, 3);
result.push.apply(result, valuesByDivisibleThree);
}
return result;
}, []);
You can get all unique values by applying a filter to the final result.
var stream = "154784587251436258748541254965874584521414174";
var columns = 9;
function groupChars(stringValue, numberOfCharacters) {
var regex = new RegExp(".{1," + numberOfCharacters + "}", "g");
return stringValue.match(regex);
}
function getNthCharacter(stringValue, index) {
return stringValue[index];
}
function isDivisibleBy(divisor) {
return function(value) {
return value % divisor === 0;
}
}
function getRowData(stream, columns) {
return groupChars(stream, columns);
}
function getColumnData(rowData, columns) {
var columnData = [];
for (var i = 0; i < columns; i++) {
columnData.push(rowData.map(function(row) {
return row[i]
}).join(''));
}
return columnData;
}
function getValuesDivisibleBy(stringValues, divisor) {
return stringValues.map(function(item) {
return parseInt(item, 10);
}).filter(isDivisibleBy(divisor));
}
function getBoxedData(stream, columns) {
var data = {};
data.rows = getRowData(stream, columns);
data.columns = getColumnData(data.rows, columns);
return data.rows.concat(data.columns);
}
var set = getBoxedData(stream, columns);
var results = set.reduce(function(result, item) {
for (var i = 0; i < item.length;) {
var values = groupChars(item, ++i);
var valuesByDivisibleThree = getValuesDivisibleBy(values, 3);
result.push.apply(result, valuesByDivisibleThree);
}
return result;
}, []);
console.log(results);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
Maybe reduce
and filter
will clean it up? No loops required ... even though there are loops running in the background.
var dataset = [
[1, 5, 4, 7, 8, 4, 5, 8, 7],
[2, 5, 1, 4, 3, 6, 2, 5, 8],
[7, 4, 8, 5, 4, 1, 2, 5, 4],
[9, 6, 5, 8, 7, 4, 5, 8, 4],
[5, 2, 1, 4, 1, 4, 1, 7, 4]
];
function isDivisibleBy(divisor) {
return function(value) {
return value % divisor === 0;
}
}
var divisibleByThree = dataset.reduce(function(accumulator, row) {
return accumulator.concat(row.filter(isDivisibleBy(3)));
}, []);
console.log(divisibleByThree)
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
Alternatively, you could just parse the string in and clean it up using regex
. Using map
and filter
would also provide the same result. This would be the same solution if you had access to the data as a 1D-array.
var stream = "154784587251436258748541254965874584521414174";
var data = stream.split(/(?!^)/);
function isDivisibleBy(divisor) {
return function(value) {
return value % divisor === 0;
}
}
var divisibleByThree = data.map(function(item) {
return parseInt(item, 10);
}).filter(isDivisibleBy(3));
console.log(divisibleByThree);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
Upvotes: 1