generated from nhcarrigan/template
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
85f80fb159
|
|||
|
bbac528845
|
@@ -16,6 +16,7 @@
|
|||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-markdown": "9.0.3",
|
"react-markdown": "9.0.3",
|
||||||
"reading-time": "1.5.0",
|
"reading-time": "1.5.0",
|
||||||
|
"rehype-highlight": "7.0.2",
|
||||||
"rehype-raw": "7.0.0",
|
"rehype-raw": "7.0.0",
|
||||||
"remark-gfm": "4.0.0"
|
"remark-gfm": "4.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+54
@@ -26,6 +26,9 @@ importers:
|
|||||||
reading-time:
|
reading-time:
|
||||||
specifier: 1.5.0
|
specifier: 1.5.0
|
||||||
version: 1.5.0
|
version: 1.5.0
|
||||||
|
rehype-highlight:
|
||||||
|
specifier: 7.0.2
|
||||||
|
version: 7.0.2
|
||||||
rehype-raw:
|
rehype-raw:
|
||||||
specifier: 7.0.0
|
specifier: 7.0.0
|
||||||
version: 7.0.0
|
version: 7.0.0
|
||||||
@@ -1602,6 +1605,9 @@ packages:
|
|||||||
hast-util-from-parse5@8.0.3:
|
hast-util-from-parse5@8.0.3:
|
||||||
resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
|
resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
|
||||||
|
|
||||||
|
hast-util-is-element@3.0.0:
|
||||||
|
resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
|
||||||
|
|
||||||
hast-util-parse-selector@4.0.0:
|
hast-util-parse-selector@4.0.0:
|
||||||
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
|
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
|
||||||
|
|
||||||
@@ -1614,12 +1620,19 @@ packages:
|
|||||||
hast-util-to-parse5@8.0.0:
|
hast-util-to-parse5@8.0.0:
|
||||||
resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
|
resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
|
||||||
|
|
||||||
|
hast-util-to-text@4.0.2:
|
||||||
|
resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==}
|
||||||
|
|
||||||
hast-util-whitespace@3.0.0:
|
hast-util-whitespace@3.0.0:
|
||||||
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
||||||
|
|
||||||
hastscript@9.0.1:
|
hastscript@9.0.1:
|
||||||
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
|
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
|
||||||
|
|
||||||
|
highlight.js@11.11.1:
|
||||||
|
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
hosted-git-info@2.8.9:
|
hosted-git-info@2.8.9:
|
||||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||||
|
|
||||||
@@ -1896,6 +1909,9 @@ packages:
|
|||||||
loupe@3.1.2:
|
loupe@3.1.2:
|
||||||
resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
|
resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
|
||||||
|
|
||||||
|
lowlight@3.3.0:
|
||||||
|
resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==}
|
||||||
|
|
||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
|
|
||||||
@@ -2374,6 +2390,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==}
|
resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
rehype-highlight@7.0.2:
|
||||||
|
resolution: {integrity: sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==}
|
||||||
|
|
||||||
rehype-raw@7.0.0:
|
rehype-raw@7.0.0:
|
||||||
resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
|
resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
|
||||||
|
|
||||||
@@ -2751,6 +2770,9 @@ packages:
|
|||||||
unified@11.0.5:
|
unified@11.0.5:
|
||||||
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
|
||||||
|
|
||||||
|
unist-util-find-after@5.0.0:
|
||||||
|
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
|
||||||
|
|
||||||
unist-util-is@6.0.0:
|
unist-util-is@6.0.0:
|
||||||
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
||||||
|
|
||||||
@@ -4651,6 +4673,10 @@ snapshots:
|
|||||||
vfile-location: 5.0.3
|
vfile-location: 5.0.3
|
||||||
web-namespaces: 2.0.1
|
web-namespaces: 2.0.1
|
||||||
|
|
||||||
|
hast-util-is-element@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
|
||||||
hast-util-parse-selector@4.0.0:
|
hast-util-parse-selector@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
@@ -4701,6 +4727,13 @@ snapshots:
|
|||||||
web-namespaces: 2.0.1
|
web-namespaces: 2.0.1
|
||||||
zwitch: 2.0.4
|
zwitch: 2.0.4
|
||||||
|
|
||||||
|
hast-util-to-text@4.0.2:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
'@types/unist': 3.0.3
|
||||||
|
hast-util-is-element: 3.0.0
|
||||||
|
unist-util-find-after: 5.0.0
|
||||||
|
|
||||||
hast-util-whitespace@3.0.0:
|
hast-util-whitespace@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
@@ -4713,6 +4746,8 @@ snapshots:
|
|||||||
property-information: 7.1.0
|
property-information: 7.1.0
|
||||||
space-separated-tokens: 2.0.2
|
space-separated-tokens: 2.0.2
|
||||||
|
|
||||||
|
highlight.js@11.11.1: {}
|
||||||
|
|
||||||
hosted-git-info@2.8.9: {}
|
hosted-git-info@2.8.9: {}
|
||||||
|
|
||||||
html-url-attributes@3.0.1: {}
|
html-url-attributes@3.0.1: {}
|
||||||
@@ -4972,6 +5007,12 @@ snapshots:
|
|||||||
|
|
||||||
loupe@3.1.2: {}
|
loupe@3.1.2: {}
|
||||||
|
|
||||||
|
lowlight@3.3.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
devlop: 1.1.0
|
||||||
|
highlight.js: 11.11.1
|
||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
magic-string@0.30.17:
|
magic-string@0.30.17:
|
||||||
@@ -5676,6 +5717,14 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
jsesc: 0.5.0
|
jsesc: 0.5.0
|
||||||
|
|
||||||
|
rehype-highlight@7.0.2:
|
||||||
|
dependencies:
|
||||||
|
'@types/hast': 3.0.4
|
||||||
|
hast-util-to-text: 4.0.2
|
||||||
|
lowlight: 3.3.0
|
||||||
|
unist-util-visit: 5.0.0
|
||||||
|
vfile: 6.0.3
|
||||||
|
|
||||||
rehype-raw@7.0.0:
|
rehype-raw@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
@@ -6179,6 +6228,11 @@ snapshots:
|
|||||||
trough: 2.2.0
|
trough: 2.2.0
|
||||||
vfile: 6.0.3
|
vfile: 6.0.3
|
||||||
|
|
||||||
|
unist-util-find-after@5.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@types/unist': 3.0.3
|
||||||
|
unist-util-is: 6.0.0
|
||||||
|
|
||||||
unist-util-is@6.0.0:
|
unist-util-is@6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
|
|||||||
@@ -4,15 +4,17 @@ date: "2025-12-10"
|
|||||||
summary: "A structured approach to programmatic problem solving."
|
summary: "A structured approach to programmatic problem solving."
|
||||||
---
|
---
|
||||||
|
|
||||||
If you have ever watched me help someone debug their code in a Discord server, you have probably noticed something: I almost never start by looking at their code. Instead, I ask them to explain their logic. What are they trying to accomplish? How do they think it should work?
|
If you've ever seen me help someone with their code, you may have noticed my unusual approach. I *never* have them start by looking at their code. Instead, I ask them to explain their logic. What are they trying to accomplish? How do they think it should work?
|
||||||
|
|
||||||
This is not because I am lazy or trying to make things difficult. It is because I have learned, through years of teaching and debugging, that **most coding problems are not actually coding problems - they are logic problems**.
|
This is not because I am lazy or trying to make things difficult. It is because I have learned, through years of teaching and debugging, that **most coding problems are not actually coding problems - they are logic problems**.
|
||||||
|
|
||||||
## The Problem with Starting with Code
|
## The Problem with Starting with Code
|
||||||
|
|
||||||
When you sit down at your keyboard and immediately start typing, you are trying to solve two problems at once: figuring out what you want to do, and figuring out how to express that in code. This is like trying to learn a new language while simultaneously trying to write a novel in it. You are juggling syntax and logic, and it is incredibly easy to drop one or both.
|
When you sit down at your keyboard and immediately start typing, you are trying to solve two problems at once. You are figuring out what you want to do, and figuring out how to make the computer do it.
|
||||||
|
|
||||||
Consider this scenario: you are trying to write a FizzBuzz algorithm. If you jump straight into code, you might write something like:
|
It's like trying to learn English by writing Shakespearian poetry. Sounds messy, right?
|
||||||
|
|
||||||
|
Let's say you are trying to write a FizzBuzz algorithm. If you start with code instead of logic, you might write something like...
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
for (let i = 1; i <= 100; i++) {
|
for (let i = 1; i <= 100; i++) {
|
||||||
@@ -26,13 +28,13 @@ for (let i = 1; i <= 100; i++) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You have already hit a problem, and you have not even finished writing the code yet. But if you had worked out the logic first, you would have caught this issue before you ever touched your keyboard.
|
You have already hit a problem, and you haven't even finished writing the code yet! If you had worked out the logic *first*, instead of jumping right into code, you would have been able to identify this problem without mucking around with the syntax.
|
||||||
|
|
||||||
## The Algorithmic Thinking Approach
|
## The Algorithmic Thinking Approach
|
||||||
|
|
||||||
Instead of starting with code, start with plain English. Write out your instructions step-by-step, as if you were explaining to a very literal, very stupid toddler who will do exactly what you say and nothing more.
|
Instead of starting with code, start with plain language. Write out your instructions. Do so one step at a time, as if you were explaining to Naomi (who will do exactly what you say and nothing more).
|
||||||
|
|
||||||
Let us use FizzBuzz as an example. Here is how I would break it down:
|
Let's use FizzBuzz as an example. Here is how I would break it down:
|
||||||
|
|
||||||
1. First, I look at the number.
|
1. First, I look at the number.
|
||||||
2. Is the number divisible by three?
|
2. Is the number divisible by three?
|
||||||
@@ -124,7 +126,7 @@ xxxxxxx
|
|||||||
xxxxxxxxx
|
xxxxxxxxx
|
||||||
```
|
```
|
||||||
|
|
||||||
But that is not a pyramid! A pyramid should be centered, like:
|
But that is not a pyramid! A pyramid should be centred, like:
|
||||||
|
|
||||||
```
|
```
|
||||||
x
|
x
|
||||||
@@ -134,7 +136,7 @@ But that is not a pyramid! A pyramid should be centered, like:
|
|||||||
xxxxxxxxx
|
xxxxxxxxx
|
||||||
```
|
```
|
||||||
|
|
||||||
The instructions were missing a crucial detail: the spacing. But more importantly, they were not precise enough. "Add two more of the same single string beside it" - beside what? Where? The instructions assumed I would understand the intent, but a computer (or a very literal person following instructions) would not.
|
The instructions were missing a crucial detail: the spacing. But more importantly, they were imprecise. "Add two more of the same single string beside it" - beside what? Where? The instructions assumed I would understand the intent, but a computer (or a very literal Naomi following instructions) would not.
|
||||||
|
|
||||||
After several iterations, we refined the instructions to be precise:
|
After several iterations, we refined the instructions to be precise:
|
||||||
|
|
||||||
@@ -160,30 +162,142 @@ Let us go back to the pyramid example. We have our logic:
|
|||||||
3. Print the spaces, then the characters.
|
3. Print the spaces, then the characters.
|
||||||
4. Move to the next row.
|
4. Move to the next row.
|
||||||
|
|
||||||
Now we can think about the code structure:
|
Now we can think about the code structure.
|
||||||
|
|
||||||
|
First, let's define our function:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
What are our steps?
|
||||||
|
|
||||||
- We need a loop to iterate through rows.
|
- We need a loop to iterate through rows.
|
||||||
- For each row, we need to calculate spaces (which decrease as rows increase).
|
- For each row, we gotta know how many spaces to use. We use less spaces in each row.
|
||||||
- For each row, we need to calculate characters (which increase as rows increase).
|
- For each row, we gotta know how many characters to use. We use more characters in each row.
|
||||||
- We need to print the combination.
|
- Finally, print our result.
|
||||||
|
|
||||||
The code almost writes itself once the logic is clear:
|
Okay, let's cretae a loop to iterate through the number of rows. Sounds like a great usecase for a standard `for` loop.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
for (let row = 0; row < numOfRows; row++) {
|
for (let row = 0; row < numOfRows; row++) {
|
||||||
const spaces = " ".repeat(numOfRows - row - 1);
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We're using `row` instead of `i`, so it's less confusing.
|
||||||
|
|
||||||
|
Now for each row (so each iteration), we gotta know how many spaces to use. Thankfully, we've already sorted that out in our logic:
|
||||||
|
|
||||||
|
> Add a number of spaces equal to the integer
|
||||||
|
> Write the whole space and string again from the last row, get rid of one space again
|
||||||
|
|
||||||
|
So we start with `numOfRows` spaces, and for each iteration we can decrement the number of spaces by one. I think, then, that we could do `numOfRows - row`. Let's put that in a variable so we don't lose track.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
|
for (let row = 0; row < numOfRows; row++) {
|
||||||
|
const spaces = " ".repeat(numOfRows - row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Alright, now the number of characters. Again, we can refer back to our paper logic:
|
||||||
|
|
||||||
|
> Write the same spaces string from before again, but get rid of one space, and write the string.
|
||||||
|
> Write the whole space and string again from the last row, get rid of one space again, and add two more of the same string.
|
||||||
|
|
||||||
|
Okay, so we start with one character, and add two more for every iteration. That would be... `row` times two, but add one to account for the initial character.
|
||||||
|
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
|
for (let row = 0; row < numOfRows; row++) {
|
||||||
|
const spaces = " ".repeat(numOfRows - row);
|
||||||
|
const characters = characterToBuildPyramidWith.repeat(row * 2 + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, our last step:
|
||||||
|
|
||||||
|
> Finally, print our result.
|
||||||
|
|
||||||
|
We can print things with a `console.log` statement. Let's print our spaces followed by our characters.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
|
for (let row = 0; row < numOfRows; row++) {
|
||||||
|
const spaces = " ".repeat(numOfRows - row);
|
||||||
const characters = characterToBuildPyramidWith.repeat(row * 2 + 1);
|
const characters = characterToBuildPyramidWith.repeat(row * 2 + 1);
|
||||||
console.log(spaces + characters);
|
console.log(spaces + characters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
But notice: I did not write this code until I had worked through the logic step-by-step. I knew exactly what I needed to calculate and why, because I had already tested the logic manually.
|
Time to double check our work! Let's call our function:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
|
for (let row = 0; row < numOfRows; row++) {
|
||||||
|
const spaces = " ".repeat(numOfRows - row);
|
||||||
|
const characters = characterToBuildPyramidWith.repeat(row * 2 + 1);
|
||||||
|
console.log(spaces + characters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pyramid("x", 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
Checking the console, I see:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
x
|
||||||
|
xxx
|
||||||
|
xxxxx
|
||||||
|
xxxxxxx
|
||||||
|
xxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
That looks like a pyramid! But hang on... It looks like we've shifted it one space too far. Let's go back to our logic on paper, because our logic is off (so we don't want to touch the code yet).
|
||||||
|
|
||||||
|
1. Look at the string. It is what we want the pyramid to be built by.
|
||||||
|
2. Look at the integer. It is the amount of rows we want.
|
||||||
|
3. Add a number of spaces equal to the integer, and then write the string.
|
||||||
|
4. Go to the next line.
|
||||||
|
5. Write the same spaces string from before again, but get rid of one space, and write the string.
|
||||||
|
6. Add two more of the same single string beside it.
|
||||||
|
7. Write the whole space and string again from the last row, get rid of one space again, and add two more of the same string.
|
||||||
|
8. Repeat step 7 until you have the same number of rows as the integer.
|
||||||
|
|
||||||
|
AHA! Our issue is in step 3.
|
||||||
|
|
||||||
|
> 3. Add a number of spaces equal to the integer, and then write the string.
|
||||||
|
|
||||||
|
By adding the number of spaces equal to the integer, we've failed to account for the initial pyramid character. Essentially, we need to add one less space.
|
||||||
|
|
||||||
|
So we update our logic **first**:
|
||||||
|
|
||||||
|
1. Look at the string. It is what we want the pyramid to be built by.
|
||||||
|
2. Look at the integer. It is the amount of rows we want.
|
||||||
|
3. Add a number of spaces equal to the integer **less one**, and then write the string.
|
||||||
|
4. Go to the next line.
|
||||||
|
5. Write the same spaces string from before again, but get rid of one space, and write the string.
|
||||||
|
6. Add two more of the same single string beside it.
|
||||||
|
7. Write the whole space and string again from the last row, get rid of one space again, and add two more of the same string.
|
||||||
|
8. Repeat step 7 until you have the same number of rows as the integer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## When Logic Breaks During Coding
|
## When Logic Breaks During Coding
|
||||||
|
|
||||||
Here is a scenario that happens all the time: you have worked out your logic, tested it manually, and it looks perfect. You start translating it to code, and halfway through, you realize something does not make sense. Maybe you cannot figure out how to express a particular step. Maybe you discover an edge case you did not consider. Maybe the logic just... does not work the way you thought it would.
|
I see it all the time. You have worked out your logic, tested it manually, and it looks perfect. You start translating it to code, and halfway through, you realize it's not perfect at all.
|
||||||
|
|
||||||
|
Maybe you cannot figure out how to achieve a specific step. Maybe you discover an edge case you did not consider. Maybe the logic just... does not work the way you thought it would.
|
||||||
|
|
||||||
**Stop coding immediately.**
|
**Stop coding immediately.**
|
||||||
|
|
||||||
@@ -203,6 +317,33 @@ Test it manually: if the integer is 5, I start with 5 spaces. Then I go to the n
|
|||||||
|
|
||||||
Now you can go back to your code with clarity. You know that for row 0, you need `numOfRows - 0 - 1` spaces (which is 4 for 5 rows). For row 1, you need `numOfRows - 1 - 1` spaces (which is 3). The pattern is clear because you worked it out in logic first.
|
Now you can go back to your code with clarity. You know that for row 0, you need `numOfRows - 0 - 1` spaces (which is 4 for 5 rows). For row 1, you need `numOfRows - 1 - 1` spaces (which is 3). The pattern is clear because you worked it out in logic first.
|
||||||
|
|
||||||
|
Okay, pretend we've tested our change manually (I am sparing you from reading through that process again), and it works. Now we can update our code to reflect our logic change:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function pyramid(characterToBuildPyramidWith, numOfRows) {
|
||||||
|
for (let row = 0; row < numOfRows; row++) {
|
||||||
|
// Notice how this is the ONLY change I made. We aren't changing anything that isn't updated in the logic on paper.
|
||||||
|
const spaces = " ".repeat(numOfRows - row - 1);
|
||||||
|
const characters = characterToBuildPyramidWith.repeat(row * 2 + 1);
|
||||||
|
console.log(spaces + characters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pyramid("x", 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
And we get:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
x
|
||||||
|
xxx
|
||||||
|
xxxxx
|
||||||
|
xxxxxxx
|
||||||
|
xxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
**WE'VE DONE IT!!!!!**
|
||||||
|
|
||||||
The key principle here is: **if you discover a logic problem while coding, you have not discovered a coding problem. You have discovered that your logic was incomplete.** Fix the logic first, test it manually, and then return to the code.
|
The key principle here is: **if you discover a logic problem while coding, you have not discovered a coding problem. You have discovered that your logic was incomplete.** Fix the logic first, test it manually, and then return to the code.
|
||||||
|
|
||||||
This might feel inefficient. You might think "I am so close, let me just fix this one thing in code." But I promise you: fixing logic in code is like trying to repair the foundation of a house while you are painting the walls. It will not work, and you will make a bigger mess.
|
This might feel inefficient. You might think "I am so close, let me just fix this one thing in code." But I promise you: fixing logic in code is like trying to repair the foundation of a house while you are painting the walls. It will not work, and you will make a bigger mess.
|
||||||
@@ -223,13 +364,14 @@ When you think algorithmically first, you gain several advantages:
|
|||||||
|
|
||||||
## The Takeaway
|
## The Takeaway
|
||||||
|
|
||||||
The next time you sit down to solve a coding problem, resist the urge to immediately start typing. Instead:
|
The next time you have to write some code, don't write the code! Do this:
|
||||||
|
|
||||||
1. Write out your logic in plain English, step-by-step.
|
1. Write out your logic in plain English, step-by-step.
|
||||||
2. Test that logic manually with several examples.
|
2. Test that logic by hand, using multiple test cases.
|
||||||
3. Refine your logic until it works perfectly.
|
3. Ideally, you've touched every "branch" in your logical breakdown.
|
||||||
4. **Only then** translate it into code.
|
3. Edit and adjust the logic when test cases fail.
|
||||||
|
4. Once all of your manual test cases pass your hand-written logic, you can finally begin translating it into code.
|
||||||
|
|
||||||
You will find that your code is cleaner, your bugs are fewer, and your problem-solving skills are stronger. And hey - if you can explain your logic to me in plain English and it works, then translating it to code is just a matter of syntax. And syntax is the easy part!
|
You will find that your code is cleaner, your bugs are fewer, and your problem-solving skills are stronger. And hey - if you can explain your logic to me in plain English and it works, then translating it to code is just a matter of syntax. And syntax is the easy part!
|
||||||
|
|
||||||
> đź’ˇ Remember: computers are really stupid toddlers who will do only and exactly what you say. Be precise, be thorough, and test your logic before you write your code.
|
> đź’ˇ Remember: computers are children who will do only and exactly what you say. Be precise, be thorough, and test your logic before you write your code.
|
||||||
|
|||||||
@@ -54,3 +54,30 @@ figcaption {
|
|||||||
@apply text-center;
|
@apply text-center;
|
||||||
@apply italic;
|
@apply italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
@apply text-left;
|
||||||
|
@apply bg-gray-100;
|
||||||
|
@apply p-2;
|
||||||
|
@apply rounded-md;
|
||||||
|
@apply border;
|
||||||
|
@apply border-gray-300;
|
||||||
|
@apply overflow-x-auto;
|
||||||
|
@apply whitespace-pre-wrap;
|
||||||
|
@apply break-words;
|
||||||
|
@apply text-sm;
|
||||||
|
@apply font-mono;
|
||||||
|
}
|
||||||
|
|
||||||
|
code:not(pre code) {
|
||||||
|
@apply text-sm;
|
||||||
|
@apply font-mono;
|
||||||
|
@apply bg-gray-100;
|
||||||
|
@apply p-1;
|
||||||
|
@apply rounded-md;
|
||||||
|
@apply border;
|
||||||
|
@apply border-gray-300;
|
||||||
|
@apply overflow-x-auto;
|
||||||
|
@apply whitespace-pre-wrap;
|
||||||
|
@apply break-words;
|
||||||
|
}
|
||||||
+6
-9
@@ -14,8 +14,7 @@ import "./globals.css";
|
|||||||
const inter = Inter({ subsets: ["latin"] });
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
const metadata: Metadata = {
|
const metadata: Metadata = {
|
||||||
description:
|
description: "The personal musings of a transfem software engineer.",
|
||||||
"The personal musings of a transfem software engineer.",
|
|
||||||
openGraph: {
|
openGraph: {
|
||||||
images: "https://cdn.nhcarrigan.com/og-image.png",
|
images: "https://cdn.nhcarrigan.com/og-image.png",
|
||||||
},
|
},
|
||||||
@@ -48,14 +47,12 @@ const RootLayout = ({
|
|||||||
strategy={"afterInteractive"}
|
strategy={"afterInteractive"}
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
></Script>
|
></Script>
|
||||||
|
<link href="https://cdn.nhcarrigan.com/logo.png" rel="icon" sizes="any" />
|
||||||
<link
|
<link
|
||||||
href="https://cdn.nhcarrigan.com/logo.png"
|
rel="stylesheet"
|
||||||
rel="icon"
|
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css"
|
||||||
sizes="any"
|
></link>
|
||||||
/>
|
<body className={inter.className}>{children}</body>
|
||||||
<body className={inter.className}>
|
|
||||||
{children}
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import Markdown from "react-markdown";
|
import Markdown from "react-markdown";
|
||||||
import rehypeRaw from "rehype-raw";
|
import rehypeRaw from "rehype-raw";
|
||||||
import remarkGfm from "remark-gfm";
|
import remarkGfm from "remark-gfm";
|
||||||
|
import rehypeHighlight from "rehype-highlight";
|
||||||
import type { JSX } from "react";
|
import type { JSX } from "react";
|
||||||
import { Rule } from "@/components/rule";
|
import { Rule } from "@/components/rule";
|
||||||
import { getPostData } from "@/lib/posts";
|
import { getPostData } from "@/lib/posts";
|
||||||
@@ -34,7 +35,7 @@ const Page = async({
|
|||||||
<h2 className="text-center">{post.data.summary}</h2>
|
<h2 className="text-center">{post.data.summary}</h2>
|
||||||
<p className="text-center">{`A ${post.data.readtime}.`}</p>
|
<p className="text-center">{`A ${post.data.readtime}.`}</p>
|
||||||
<Rule />
|
<Rule />
|
||||||
<Markdown rehypePlugins={[ rehypeRaw ]} remarkPlugins={[ remarkGfm ]}>
|
<Markdown rehypePlugins={[ rehypeRaw, rehypeHighlight ]} remarkPlugins={[ remarkGfm ]}>
|
||||||
{post.content}
|
{post.content}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
<Rule />
|
<Rule />
|
||||||
|
|||||||
Reference in New Issue
Block a user