Plotting hearts with Python and C
github.com
github.com
Seriously, though, it's a little heartwarming bouquet.
Relatedly, there is this video on how to procedurally generate a 3D heart:
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: https://www.wolframalpha.com/input/?i=Re%28-sqrt%281%20-%20s...
PART 3 - Plotting the Two Curves Together
Let us combine the two equations together. The equations for both curves are: y = sqrt(|x|(1 - |x|)), y = -sqrt(1 - sqrt(|x|)). Plot: https://www.wolframalpha.com/input/?i=%7By%20%3D%20Re%28sqrt...
PART 4 - Scaling the Second Curve
Finally, in the actual plot I printed, laminated, and presented to my girlfriend, I have multiplied the second equation by 1.5 to stretch the bottommost point of the heart from y = -1 to y = -1.5. Since I used equal scaling (aspect ratio = 1) for both axes and printed it without any scaling to get a high quality print, stretching the bottom of the heart was necessary to make the heart look beautiful and wholesome. Plot: https://github.com/susam/heart/blob/master/heart-2014-02-14....
The time actually has a write up on the formula too https://www.nytimes.com/2019/02/14/science/math-algorithm-va...
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?
for (i = 0; i < sizeof love / sizeof *love; i++)
if (love[i] < 4)
printf("%s", say[love[i]]);
else
for (j = 0; j < love[i] / 4; j++)
putchar(show[love[i] % 4]);
Yes, C doesn't force you to use braces here, but this is really overdoing it.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.
#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.
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
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;
}Demanding 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.