Given many rectangles, whats the best approach to group by line
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
TLDR: How to find boxes that are lined up horizontally
Given I have the data from an image like this:
We can visually see that we have two lines:
Tare: 11700 kg 10:40:58 am 16-May
Gross: 21300 kg 12:49:34 pm 9-Aug
The data I have for each blue box shown in the image is:
Top
Left
Width
Height
- Coordinates for each corner of the box (
X
,Y
)
My main thought is to start from the top of my "grid" and loop through each value of y, and then group boxes where they share the largest amount of matching "y" values, but it seems very over the top for something that seems simple.
Unsure really where to go from here
Example data set
I was able to get boxes lined up using this bit of code (in JavaScript), it essentially finds the first "most top left" box, and then finds any boxes that "intersect" with a line that starts from the middle of that first box
We don't care what order we get the boxes in, so as long as we start with the most left on any line we are golden.
function getMostTopLeftBox(boxes)
const sorted = boxes.slice()
.sort(
(a, b) =>
if (a.Left === b.Left)
return a.Top < b.Top ? -1 : 1;
return a.Left < b.Left ? -1 : 1;
);
return sorted[0];
function getAlignedBoxesFromSet(boxes)
const mostTopLeftBox = getMostTopLeftBox(boxes);
const line = mostTopLeftBox.Top + (mostTopLeftBox.Height / 2);
return boxes
.filter(( Top, Height ) => Top < line && (Top + Height) > line)
.sort(( Left: a , Left: b ) => a < b ? -1 : 1)
function getAlignedBoxes(boxes)
let remaining = boxes;
const lines = ;
const next = () =>
const line = getAlignedBoxesFromSet(remaining);
lines.push(line);
remaining = remaining.filter(box => line.indexOf(box) === -1);
if (!remaining.length)
return;
return next();
;
next();
return lines;
The above code with the data set provided above gives us this result
However, it doesn't account for slight angles on the boxes, for example this image:
Another example of different boxes, with senstive information removed:
You can see from the above that the values below should be considered to be on the same line:
Product: [type]
Num Of [type]: 0
[value]: [value]
I may make a new question for this, but part of the answer to this is to figure out the actual curve of a line, and not just assume that the median angle of all lines is the actual "curve" of the line, so if I was to start with the most left box, then progress to the second box, now I have two distinct lines that I would want to find the smoothed curve for, which I would then use to find the next box, as I find each box I would want to adjust this curve to find the complete line, I will investigate this one further, if anyone has any hints, please do mention it.
math language-agnostic geometry
add a comment |
TLDR: How to find boxes that are lined up horizontally
Given I have the data from an image like this:
We can visually see that we have two lines:
Tare: 11700 kg 10:40:58 am 16-May
Gross: 21300 kg 12:49:34 pm 9-Aug
The data I have for each blue box shown in the image is:
Top
Left
Width
Height
- Coordinates for each corner of the box (
X
,Y
)
My main thought is to start from the top of my "grid" and loop through each value of y, and then group boxes where they share the largest amount of matching "y" values, but it seems very over the top for something that seems simple.
Unsure really where to go from here
Example data set
I was able to get boxes lined up using this bit of code (in JavaScript), it essentially finds the first "most top left" box, and then finds any boxes that "intersect" with a line that starts from the middle of that first box
We don't care what order we get the boxes in, so as long as we start with the most left on any line we are golden.
function getMostTopLeftBox(boxes)
const sorted = boxes.slice()
.sort(
(a, b) =>
if (a.Left === b.Left)
return a.Top < b.Top ? -1 : 1;
return a.Left < b.Left ? -1 : 1;
);
return sorted[0];
function getAlignedBoxesFromSet(boxes)
const mostTopLeftBox = getMostTopLeftBox(boxes);
const line = mostTopLeftBox.Top + (mostTopLeftBox.Height / 2);
return boxes
.filter(( Top, Height ) => Top < line && (Top + Height) > line)
.sort(( Left: a , Left: b ) => a < b ? -1 : 1)
function getAlignedBoxes(boxes)
let remaining = boxes;
const lines = ;
const next = () =>
const line = getAlignedBoxesFromSet(remaining);
lines.push(line);
remaining = remaining.filter(box => line.indexOf(box) === -1);
if (!remaining.length)
return;
return next();
;
next();
return lines;
The above code with the data set provided above gives us this result
However, it doesn't account for slight angles on the boxes, for example this image:
Another example of different boxes, with senstive information removed:
You can see from the above that the values below should be considered to be on the same line:
Product: [type]
Num Of [type]: 0
[value]: [value]
I may make a new question for this, but part of the answer to this is to figure out the actual curve of a line, and not just assume that the median angle of all lines is the actual "curve" of the line, so if I was to start with the most left box, then progress to the second box, now I have two distinct lines that I would want to find the smoothed curve for, which I would then use to find the next box, as I find each box I would want to adjust this curve to find the complete line, I will investigate this one further, if anyone has any hints, please do mention it.
math language-agnostic geometry
Maybe look at the intervals of eachTop
toTop + Height
, compare it with previous intervals by calculating the overlap and grouping accordingly?
– TrebledJ
Nov 15 '18 at 8:57
Can the boxes overlap? Are the lines always horizontal or can they be tilted?
– Nico Schertler
Nov 15 '18 at 17:01
The lines can be tilted slightly, and I there is the possibility to overlap, but almost never will happen, the data I receive is usually like the example. @TrebuchetMS I had used the middle of the first box to find a "middle line" for that line, and then compare other boxes to that, but I feel like I am missing some cases.
– FabianCook
Nov 15 '18 at 20:56
Another way you could do this... start off with a matrix, fill in the first column (Fare, Gross, etc) by looking at smallestLeft
's. Group each box into columns by looking at the intervals. Then add those columns to your matrix. (This is logically better than parsing individual rows. Since the angles are "slight" there shouldn't be as much horizontal variation as there would be vertical variation. But again, this may not work for say angles >30º.) Sounds like a cool ML project you're working on. :-)
– TrebledJ
Nov 16 '18 at 1:15
Definitely a cool project. The images posted above are some generic examples of the info that could be collected, I've added more that shows some more data, showing that organizing by columns could be a bit harder.
– FabianCook
Nov 16 '18 at 4:25
add a comment |
TLDR: How to find boxes that are lined up horizontally
Given I have the data from an image like this:
We can visually see that we have two lines:
Tare: 11700 kg 10:40:58 am 16-May
Gross: 21300 kg 12:49:34 pm 9-Aug
The data I have for each blue box shown in the image is:
Top
Left
Width
Height
- Coordinates for each corner of the box (
X
,Y
)
My main thought is to start from the top of my "grid" and loop through each value of y, and then group boxes where they share the largest amount of matching "y" values, but it seems very over the top for something that seems simple.
Unsure really where to go from here
Example data set
I was able to get boxes lined up using this bit of code (in JavaScript), it essentially finds the first "most top left" box, and then finds any boxes that "intersect" with a line that starts from the middle of that first box
We don't care what order we get the boxes in, so as long as we start with the most left on any line we are golden.
function getMostTopLeftBox(boxes)
const sorted = boxes.slice()
.sort(
(a, b) =>
if (a.Left === b.Left)
return a.Top < b.Top ? -1 : 1;
return a.Left < b.Left ? -1 : 1;
);
return sorted[0];
function getAlignedBoxesFromSet(boxes)
const mostTopLeftBox = getMostTopLeftBox(boxes);
const line = mostTopLeftBox.Top + (mostTopLeftBox.Height / 2);
return boxes
.filter(( Top, Height ) => Top < line && (Top + Height) > line)
.sort(( Left: a , Left: b ) => a < b ? -1 : 1)
function getAlignedBoxes(boxes)
let remaining = boxes;
const lines = ;
const next = () =>
const line = getAlignedBoxesFromSet(remaining);
lines.push(line);
remaining = remaining.filter(box => line.indexOf(box) === -1);
if (!remaining.length)
return;
return next();
;
next();
return lines;
The above code with the data set provided above gives us this result
However, it doesn't account for slight angles on the boxes, for example this image:
Another example of different boxes, with senstive information removed:
You can see from the above that the values below should be considered to be on the same line:
Product: [type]
Num Of [type]: 0
[value]: [value]
I may make a new question for this, but part of the answer to this is to figure out the actual curve of a line, and not just assume that the median angle of all lines is the actual "curve" of the line, so if I was to start with the most left box, then progress to the second box, now I have two distinct lines that I would want to find the smoothed curve for, which I would then use to find the next box, as I find each box I would want to adjust this curve to find the complete line, I will investigate this one further, if anyone has any hints, please do mention it.
math language-agnostic geometry
TLDR: How to find boxes that are lined up horizontally
Given I have the data from an image like this:
We can visually see that we have two lines:
Tare: 11700 kg 10:40:58 am 16-May
Gross: 21300 kg 12:49:34 pm 9-Aug
The data I have for each blue box shown in the image is:
Top
Left
Width
Height
- Coordinates for each corner of the box (
X
,Y
)
My main thought is to start from the top of my "grid" and loop through each value of y, and then group boxes where they share the largest amount of matching "y" values, but it seems very over the top for something that seems simple.
Unsure really where to go from here
Example data set
I was able to get boxes lined up using this bit of code (in JavaScript), it essentially finds the first "most top left" box, and then finds any boxes that "intersect" with a line that starts from the middle of that first box
We don't care what order we get the boxes in, so as long as we start with the most left on any line we are golden.
function getMostTopLeftBox(boxes)
const sorted = boxes.slice()
.sort(
(a, b) =>
if (a.Left === b.Left)
return a.Top < b.Top ? -1 : 1;
return a.Left < b.Left ? -1 : 1;
);
return sorted[0];
function getAlignedBoxesFromSet(boxes)
const mostTopLeftBox = getMostTopLeftBox(boxes);
const line = mostTopLeftBox.Top + (mostTopLeftBox.Height / 2);
return boxes
.filter(( Top, Height ) => Top < line && (Top + Height) > line)
.sort(( Left: a , Left: b ) => a < b ? -1 : 1)
function getAlignedBoxes(boxes)
let remaining = boxes;
const lines = ;
const next = () =>
const line = getAlignedBoxesFromSet(remaining);
lines.push(line);
remaining = remaining.filter(box => line.indexOf(box) === -1);
if (!remaining.length)
return;
return next();
;
next();
return lines;
The above code with the data set provided above gives us this result
However, it doesn't account for slight angles on the boxes, for example this image:
Another example of different boxes, with senstive information removed:
You can see from the above that the values below should be considered to be on the same line:
Product: [type]
Num Of [type]: 0
[value]: [value]
I may make a new question for this, but part of the answer to this is to figure out the actual curve of a line, and not just assume that the median angle of all lines is the actual "curve" of the line, so if I was to start with the most left box, then progress to the second box, now I have two distinct lines that I would want to find the smoothed curve for, which I would then use to find the next box, as I find each box I would want to adjust this curve to find the complete line, I will investigate this one further, if anyone has any hints, please do mention it.
math language-agnostic geometry
math language-agnostic geometry
edited Nov 16 '18 at 8:20
FabianCook
asked Nov 15 '18 at 7:09
FabianCookFabianCook
12.2k145199
12.2k145199
Maybe look at the intervals of eachTop
toTop + Height
, compare it with previous intervals by calculating the overlap and grouping accordingly?
– TrebledJ
Nov 15 '18 at 8:57
Can the boxes overlap? Are the lines always horizontal or can they be tilted?
– Nico Schertler
Nov 15 '18 at 17:01
The lines can be tilted slightly, and I there is the possibility to overlap, but almost never will happen, the data I receive is usually like the example. @TrebuchetMS I had used the middle of the first box to find a "middle line" for that line, and then compare other boxes to that, but I feel like I am missing some cases.
– FabianCook
Nov 15 '18 at 20:56
Another way you could do this... start off with a matrix, fill in the first column (Fare, Gross, etc) by looking at smallestLeft
's. Group each box into columns by looking at the intervals. Then add those columns to your matrix. (This is logically better than parsing individual rows. Since the angles are "slight" there shouldn't be as much horizontal variation as there would be vertical variation. But again, this may not work for say angles >30º.) Sounds like a cool ML project you're working on. :-)
– TrebledJ
Nov 16 '18 at 1:15
Definitely a cool project. The images posted above are some generic examples of the info that could be collected, I've added more that shows some more data, showing that organizing by columns could be a bit harder.
– FabianCook
Nov 16 '18 at 4:25
add a comment |
Maybe look at the intervals of eachTop
toTop + Height
, compare it with previous intervals by calculating the overlap and grouping accordingly?
– TrebledJ
Nov 15 '18 at 8:57
Can the boxes overlap? Are the lines always horizontal or can they be tilted?
– Nico Schertler
Nov 15 '18 at 17:01
The lines can be tilted slightly, and I there is the possibility to overlap, but almost never will happen, the data I receive is usually like the example. @TrebuchetMS I had used the middle of the first box to find a "middle line" for that line, and then compare other boxes to that, but I feel like I am missing some cases.
– FabianCook
Nov 15 '18 at 20:56
Another way you could do this... start off with a matrix, fill in the first column (Fare, Gross, etc) by looking at smallestLeft
's. Group each box into columns by looking at the intervals. Then add those columns to your matrix. (This is logically better than parsing individual rows. Since the angles are "slight" there shouldn't be as much horizontal variation as there would be vertical variation. But again, this may not work for say angles >30º.) Sounds like a cool ML project you're working on. :-)
– TrebledJ
Nov 16 '18 at 1:15
Definitely a cool project. The images posted above are some generic examples of the info that could be collected, I've added more that shows some more data, showing that organizing by columns could be a bit harder.
– FabianCook
Nov 16 '18 at 4:25
Maybe look at the intervals of each
Top
to Top + Height
, compare it with previous intervals by calculating the overlap and grouping accordingly?– TrebledJ
Nov 15 '18 at 8:57
Maybe look at the intervals of each
Top
to Top + Height
, compare it with previous intervals by calculating the overlap and grouping accordingly?– TrebledJ
Nov 15 '18 at 8:57
Can the boxes overlap? Are the lines always horizontal or can they be tilted?
– Nico Schertler
Nov 15 '18 at 17:01
Can the boxes overlap? Are the lines always horizontal or can they be tilted?
– Nico Schertler
Nov 15 '18 at 17:01
The lines can be tilted slightly, and I there is the possibility to overlap, but almost never will happen, the data I receive is usually like the example. @TrebuchetMS I had used the middle of the first box to find a "middle line" for that line, and then compare other boxes to that, but I feel like I am missing some cases.
– FabianCook
Nov 15 '18 at 20:56
The lines can be tilted slightly, and I there is the possibility to overlap, but almost never will happen, the data I receive is usually like the example. @TrebuchetMS I had used the middle of the first box to find a "middle line" for that line, and then compare other boxes to that, but I feel like I am missing some cases.
– FabianCook
Nov 15 '18 at 20:56
Another way you could do this... start off with a matrix, fill in the first column (Fare, Gross, etc) by looking at smallest
Left
's. Group each box into columns by looking at the intervals. Then add those columns to your matrix. (This is logically better than parsing individual rows. Since the angles are "slight" there shouldn't be as much horizontal variation as there would be vertical variation. But again, this may not work for say angles >30º.) Sounds like a cool ML project you're working on. :-)– TrebledJ
Nov 16 '18 at 1:15
Another way you could do this... start off with a matrix, fill in the first column (Fare, Gross, etc) by looking at smallest
Left
's. Group each box into columns by looking at the intervals. Then add those columns to your matrix. (This is logically better than parsing individual rows. Since the angles are "slight" there shouldn't be as much horizontal variation as there would be vertical variation. But again, this may not work for say angles >30º.) Sounds like a cool ML project you're working on. :-)– TrebledJ
Nov 16 '18 at 1:15
Definitely a cool project. The images posted above are some generic examples of the info that could be collected, I've added more that shows some more data, showing that organizing by columns could be a bit harder.
– FabianCook
Nov 16 '18 at 4:25
Definitely a cool project. The images posted above are some generic examples of the info that could be collected, I've added more that shows some more data, showing that organizing by columns could be a bit harder.
– FabianCook
Nov 16 '18 at 4:25
add a comment |
1 Answer
1
active
oldest
votes
I've managed to solve this, with a variant of the code posted in the question.
Here is a code sandbox of the solution, I will do a full write up of this, but here it is for now: https://codesandbox.io/s/102xnl7on3
Here is an example of grouped boxes based on angled lines calculated from the angle of all horizontal lines, if all the boxes were to be straight, then the result would be the lines being straight as well, so it should work in all scenarios.
Here is also an example where the lines are straight:
You can see the lines from the box before intersecting with the next box, it does this each time until it can find a complete line of boxes (till no more line up), this works out better than using an average angle from the entire data set.
I would like to be able to generate a mathematical curve for the already found boxes and apply that to find the next box, but for now, using the previous box as the anchor works pretty well.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53314113%2fgiven-many-rectangles-whats-the-best-approach-to-group-by-line%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I've managed to solve this, with a variant of the code posted in the question.
Here is a code sandbox of the solution, I will do a full write up of this, but here it is for now: https://codesandbox.io/s/102xnl7on3
Here is an example of grouped boxes based on angled lines calculated from the angle of all horizontal lines, if all the boxes were to be straight, then the result would be the lines being straight as well, so it should work in all scenarios.
Here is also an example where the lines are straight:
You can see the lines from the box before intersecting with the next box, it does this each time until it can find a complete line of boxes (till no more line up), this works out better than using an average angle from the entire data set.
I would like to be able to generate a mathematical curve for the already found boxes and apply that to find the next box, but for now, using the previous box as the anchor works pretty well.
add a comment |
I've managed to solve this, with a variant of the code posted in the question.
Here is a code sandbox of the solution, I will do a full write up of this, but here it is for now: https://codesandbox.io/s/102xnl7on3
Here is an example of grouped boxes based on angled lines calculated from the angle of all horizontal lines, if all the boxes were to be straight, then the result would be the lines being straight as well, so it should work in all scenarios.
Here is also an example where the lines are straight:
You can see the lines from the box before intersecting with the next box, it does this each time until it can find a complete line of boxes (till no more line up), this works out better than using an average angle from the entire data set.
I would like to be able to generate a mathematical curve for the already found boxes and apply that to find the next box, but for now, using the previous box as the anchor works pretty well.
add a comment |
I've managed to solve this, with a variant of the code posted in the question.
Here is a code sandbox of the solution, I will do a full write up of this, but here it is for now: https://codesandbox.io/s/102xnl7on3
Here is an example of grouped boxes based on angled lines calculated from the angle of all horizontal lines, if all the boxes were to be straight, then the result would be the lines being straight as well, so it should work in all scenarios.
Here is also an example where the lines are straight:
You can see the lines from the box before intersecting with the next box, it does this each time until it can find a complete line of boxes (till no more line up), this works out better than using an average angle from the entire data set.
I would like to be able to generate a mathematical curve for the already found boxes and apply that to find the next box, but for now, using the previous box as the anchor works pretty well.
I've managed to solve this, with a variant of the code posted in the question.
Here is a code sandbox of the solution, I will do a full write up of this, but here it is for now: https://codesandbox.io/s/102xnl7on3
Here is an example of grouped boxes based on angled lines calculated from the angle of all horizontal lines, if all the boxes were to be straight, then the result would be the lines being straight as well, so it should work in all scenarios.
Here is also an example where the lines are straight:
You can see the lines from the box before intersecting with the next box, it does this each time until it can find a complete line of boxes (till no more line up), this works out better than using an average angle from the entire data set.
I would like to be able to generate a mathematical curve for the already found boxes and apply that to find the next box, but for now, using the previous box as the anchor works pretty well.
edited Nov 16 '18 at 10:40
answered Nov 16 '18 at 7:58
FabianCookFabianCook
12.2k145199
12.2k145199
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53314113%2fgiven-many-rectangles-whats-the-best-approach-to-group-by-line%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Maybe look at the intervals of each
Top
toTop + Height
, compare it with previous intervals by calculating the overlap and grouping accordingly?– TrebledJ
Nov 15 '18 at 8:57
Can the boxes overlap? Are the lines always horizontal or can they be tilted?
– Nico Schertler
Nov 15 '18 at 17:01
The lines can be tilted slightly, and I there is the possibility to overlap, but almost never will happen, the data I receive is usually like the example. @TrebuchetMS I had used the middle of the first box to find a "middle line" for that line, and then compare other boxes to that, but I feel like I am missing some cases.
– FabianCook
Nov 15 '18 at 20:56
Another way you could do this... start off with a matrix, fill in the first column (Fare, Gross, etc) by looking at smallest
Left
's. Group each box into columns by looking at the intervals. Then add those columns to your matrix. (This is logically better than parsing individual rows. Since the angles are "slight" there shouldn't be as much horizontal variation as there would be vertical variation. But again, this may not work for say angles >30º.) Sounds like a cool ML project you're working on. :-)– TrebledJ
Nov 16 '18 at 1:15
Definitely a cool project. The images posted above are some generic examples of the info that could be collected, I've added more that shows some more data, showing that organizing by columns could be a bit harder.
– FabianCook
Nov 16 '18 at 4:25