Definitely reminds me of my highschool days. Except my gift was written in turbo pascal and could rotate around the Y axis without any flicker on a 486 DX. Drawing a heart on a TI-86 was too easy, so I had to up my game.
"Could I have that big red fluffy arse?"
"Do you mean this plush heart?"
"No. I'm a cardiologist, I've been operating on human hearts for the last 20 years, I know how a heart looks like, and I would very much like that red fluffy arse."
Seriously, though, it's a little heartwarming bouquet.
What's wrong with it is that it's really really easy to make a mistake and introduce a subtle bug that will be hard to spot.
Especially now since languages like python have been developed that have made people used to indentation-defined code.
It's the style in K&R? Ok, so the literal inventor of the language was certain he wouldn't make this kind of mistake, that still doesn't mean I trust myself not to.
Omitting braces for single statements is quite idiomatic in the C development world, whether we like it or not. If we don't trust ourselves that we wouldn't make this kind of mistake, use the right tooling: 'gcc -Wall' (since GCC 6) or 'clang-format' can easily detect misleading indentation.
I don't have a copy of K&R handy, but I feel like I would remember if it really had an example like this nested three levels deep. I would be grateful if someone could check.
#include <stdio.h>
/* count lines in input */
main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
}
§ 1.5.4 Word Counting
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
Also, see § 1.6 Arrays, § 2.8 Increment and Decrement Operators, etc.
By the way, I would always use brace while working on a team project where there are other developers involved. But this is a one-time, personal, and hobby project where I am the only developer and I prefer to choose the K&R style when nobody else is involved.
Wow, that was quick, thanks. Though the first example is only two levels deep and also less complex than your code in question, which has a loop in the else part of an if in a loop...
The second example uses braces (as it must), so it's not an example of what I was asking for.
Okay, I was counting the nesting depth incorrectly. Here are a few more examples:
§ 3.8 Goto and labels
found = 0;
for (i = 0; i < n && !found; i++)
for (j = 0; j < m && !found; j++)
if (a[i] == b[j])
found = 1;
if (found)
/* got one: a[i-1] == b[j-1] */
...
else
/* didn't find any common element */
§ 6.3 Arrays of Structures
/* count C keywords */
main()
{
int n;
char word[MAXWORD];
while (getword(word, MAXWORD) != EOF)
if (isalpha(word[0]))
if ((n = binsearch(word, keytab, NKEYS)) >= 0)
keytab[n].count++;
for (n = 0; n < NKEYS; n++)
if (keytab[n].count > 0)
printf("%4d %s\n",
keytab[n].count, keytab[n].word);
return 0;
}
Thanks. I still find these a bit more palatable than your loop-in-an-else-in-a-loop (there are no elses and no loops inside ifs here), but yeah, I can imagine that K&R might have written it the same way as you did.
The second example does lack braces in two nested 'if' statements. Did you ignore that? Granted it is not three levels deep and granted there is a brace in the 'else' part but that's no reason to ignore the fact that K&R does in fact omit the braces for nested 'if-else' statements.
Demanding now that the nesting has to be less than three levels deep to omit braces is just moving the goalposts.
> Yes, C doesn't force you to use braces here, but this is really overdoing it.
It said nothing about nesting level depth. The question of nesting level appeared later in a child comment of yours which I believe is moving the goalposts. Sorry, I didn't make this clear in my previous comment.
I used to code like that for a long time so it doesn't bother me too much. Then I started learning Rust (which uses a C-style syntax but makes braces mandatory ever for single statements) and I started doing it even in C. In hindsight I feel stupid for not doing it earlier, it doesn't add too much noise (at least if you put the opening brace on the same line) and it wards off many potential nasty bugs if you copy code around or use poorly written macros.
My rule has always been that if you're going to write a single line if-statement it should actually be a single line if-statement, i.e. no line break between the condition and the curly bracket.
I coded like this when I was self taught and then in college. Once I got my first programming job and started fixing other people's bugs that the braces would have avoided, I stopped doing this.
The content is completely irrelevant, s/he only showed dislike of the indentation with which I disagree. What does it matter whether or not it says "I love you"? Should we not be able to criticize any other aspects of code when it prints or displays something positive?
A cardoid is a popular way of plotting a heart shaped curve. However, I mentioned in another comment in this thread that the heart plotted with Python and Matplotlib in this repository is not made of cardoid. Instead, it is made of semicircles and quartic curves. Here's the comment with more details: https://news.ycombinator.com/item?id=19162360.
I was expecting it to be the same algorithm in two different languages, but the Python version is a mathematical description whereas the C version is RLE-compressed.
Relatedly, there is this video on how to procedurally generate a 3D heart:
The two functions from Python one: y = sqrt(1 - |x|) * sqrt(|x|), y = (-3/2) * sqrt(1 - sqrt(|x|)). How do they produce the desired output? Is there a way to construct such functions?
Some of the "plot" links to WolframAlpha in that thread do not show the example graphs anymore, so let me rewrite that comment here with updated links. Rewritten comment with updated link now follows.
---
I wanted something that resembles the hearts in playing cards more than it resembles a cardoid, so I made a simpler heart for my girlfriend (now my wife) composed of two simple curves. The heart is plotted with two semicircles and segments of two quartic curves. Here is an explanation of how I arrived at these equations.
With the previous equation, we got both negative and positive values of y, hence a full circle. We want to eliminate the negative values of y, thereby resulting in a semicircle lying above the x-axis. We take square root of both sides: y = sqrt(x(1 - x)). Plot: https://www.wolframalpha.com/input/?i=sqrt%28x%281%20-%20x%2...
Now, we want a mirror image of this curve on the left side of the y-axis, i.e., for negative values of x, we want the same values of y that we see in the above plot. We do this by substituting x with |x| in the above equation: y = sqrt(|x|(1 - |x|)). Plot: https://www.wolframalpha.com/input/?i=Re%28sqrt%28abs%28x%29...
This completes the top portion of the heart with two semicircles.
PART 2 - Plotting the Segments of Two Quartic Curves
Now we try to complete the bottom portion of the heart. I didn't start with quartic curves. Instead, I began with parabolas and arrived at quartic curves. We begin with a single parabola: y^2 = 1 - x. Plot: https://www.wolframalpha.com/input/?i=y%5E2+%3D+1+-+x
But I wanted to get a little bit of concave curvature at the bottom of the curves to resemble the hearts in playing cards. I could get this by a little trick I learnt somewhere online: We can vary the power of |x| between 0.5 and 1.0 to get different curvatures, i.e., we can vary r in y = -sqrt(1 - |x|^r) where 0.5 <= r <= 1.0 to get different curvatures. I liked the concave curvature with r = 0.5, so I chose y = -sqrt(1 - sqrt(|x|)). This turns the segments of parabolas into segments of quartic curves. Plot: <...
39 comments
[ 4.3 ms ] story [ 122 ms ] threadSeriously, though, it's a little heartwarming bouquet.
And I say this as someone who does like Python's indentation-based syntax. Doing the same in C is not idiomatic.
It's the style in K&R? Ok, so the literal inventor of the language was certain he wouldn't make this kind of mistake, that still doesn't mean I trust myself not to.
By the way, I would always use brace while working on a team project where there are other developers involved. But this is a one-time, personal, and hobby project where I am the only developer and I prefer to choose the K&R style when nobody else is involved.
The second example uses braces (as it must), so it's not an example of what I was asking for.
§ 3.8 Goto and labels
§ 6.3 Arrays of StructuresDemanding now that the nesting has to be less than three levels deep to omit braces is just moving the goalposts.
Yeah, "else if" is a special case where I wouldn't put braces even if I prefer them everywhere else.
> Demanding now that the nesting has to be less than three levels deep
I specifically asked for a three levels before, in https://news.ycombinator.com/item?id=19162933, not "now".
> Yes, C doesn't force you to use braces here, but this is really overdoing it.
It said nothing about nesting level depth. The question of nesting level appeared later in a child comment of yours which I believe is moving the goalposts. Sorry, I didn't make this clear in my previous comment.
Having said that, I do agree with you that braces are helpful. But then, we should all decide the pants policy in our own homes: https://groups.google.com/d/msg/nodejs/MWaivVTirPY/0pnRjKsgg...
It's exactly as you might see in K&R, and short enough that there's never going to be confusion from their lack.
Yeah, well... I am lonely. :(
Good thing we can indicate our love with persnickety comments and have no need for such a program.
y = sqrt(1 - |x|) * sqrt(|x|)
y = (-3/2) * sqrt(1 - sqrt(|x|))
Why do these equations work and look like heart? How does one make such equations?
Relatedly, there is this video on how to procedurally generate a 3D heart:
https://www.youtube.com/watch?v=aNR4n0i2ZlM
Some of the "plot" links to WolframAlpha in that thread do not show the example graphs anymore, so let me rewrite that comment here with updated links. Rewritten comment with updated link now follows.
---
I wanted something that resembles the hearts in playing cards more than it resembles a cardoid, so I made a simpler heart for my girlfriend (now my wife) composed of two simple curves. The heart is plotted with two semicircles and segments of two quartic curves. Here is an explanation of how I arrived at these equations.
PART 1 - Plotting the Two Semicircles
First, we want to draw a circle of radius 1/2 centered at (1/2, 0). We start with an equation of a circle: (x - 1/2)^2 + y^2 = (1/2)^2 ⇔ x^2 - x + y^2 = 0 ⇔ y^2 = x(1 - x). Plot: https://www.wolframalpha.com/input/?i=y%5E2%20%3D%20x%281%20...
With the previous equation, we got both negative and positive values of y, hence a full circle. We want to eliminate the negative values of y, thereby resulting in a semicircle lying above the x-axis. We take square root of both sides: y = sqrt(x(1 - x)). Plot: https://www.wolframalpha.com/input/?i=sqrt%28x%281%20-%20x%2...
Now, we want a mirror image of this curve on the left side of the y-axis, i.e., for negative values of x, we want the same values of y that we see in the above plot. We do this by substituting x with |x| in the above equation: y = sqrt(|x|(1 - |x|)). Plot: https://www.wolframalpha.com/input/?i=Re%28sqrt%28abs%28x%29...
This completes the top portion of the heart with two semicircles.
PART 2 - Plotting the Segments of Two Quartic Curves
Now we try to complete the bottom portion of the heart. I didn't start with quartic curves. Instead, I began with parabolas and arrived at quartic curves. We begin with a single parabola: y^2 = 1 - x. Plot: https://www.wolframalpha.com/input/?i=y%5E2+%3D+1+-+x
We go through the same drill. We first eliminate negative values of y and then mirror the graph on the left side of the y axis: y = sqrt(1 - |x|). Plot: https://www.wolframalpha.com/input/?i=Re%28sqrt%281%20-%20ab...
Let us get a mirror of this plot below the x-axis by multiplying the right hand side by -1: y = -sqrt(1 - |x|). Plot: https://www.wolframalpha.com/input/?i=Re%28-sqrt%281%20-%20a...
But I wanted to get a little bit of concave curvature at the bottom of the curves to resemble the hearts in playing cards. I could get this by a little trick I learnt somewhere online: We can vary the power of |x| between 0.5 and 1.0 to get different curvatures, i.e., we can vary r in y = -sqrt(1 - |x|^r) where 0.5 <= r <= 1.0 to get different curvatures. I liked the concave curvature with r = 0.5, so I chose y = -sqrt(1 - sqrt(|x|)). This turns the segments of parabolas into segments of quartic curves. Plot: <...
The time actually has a write up on the formula too https://www.nytimes.com/2019/02/14/science/math-algorithm-va...