Tiny program to print out somewhat ASCII-artish graphs with "sensible" words, which in my case were qw/baci besos kisses/: it's thought as a sort of gift for a very special person who happens to be much mathematically inclined and talented, let alone artistically.

(The most relevant part of the code is in the process() sub, which in fact is run only once and thus may have been inlined instead. But I preferred to factor it away, so I'm perhaps slightly violating YAGNI, however it may make life easier for further developments.)

#!/usr/bin/perl use strict; use warnings; use constant { LEN => 75, PI => 3.14159265359 }; sub process; process [0, 2.3875*PI], [-1, 1], 382, baci => sub { cos(1/($_[0]+.05)**.5) }, besos => sub { -cos(1/($_[0]+.15)**.78) }, kisses => sub { sin($_[0]) }; sub process { my ($xr, $yr, $lines, %funcs)=@_; my $m=($xr->[1]-$xr->[0])/($lines-1); my $q=$xr->[0]-$m; my %m = map { $_ => (LEN-length)/($yr->[1]-$yr->[0]) } keys %funcs; my %q = map { $_ => -$m{$_} * $yr->[0] } keys %funcs; for (1..$lines) { my $x=$m*$_+$q; my @str = sort {length($b) <=> length($a)} map ' ' x ($m{$_} * $funcs{$_}($x) + $q{$_}) . $_, keys %funcs; my $base=shift @str; substr $base, 0, length, $_ for @str; print $base, "\n"; } } __END__

Replies are listed 'Best First'.
Re: [ASCII art graphs] Kisses
by dewey (Pilgrim) on Jun 13, 2007 at 16:01 UTC
    Nice effect. Reminds me of lissajous from my Basic days...

    ~dewey

      Very good idea. I used to draw such curves with basic too. So here's a perl one, just to disprove blazar's statement.

      #!perl use warnings; use strict; sub pie() { 2 * atan2(1, 0); } sub asin { atan2($_[0], sqrt(1 - $_[0]**2)); } sub liss { my($p_m, $p_n, $p_d) = @_; my($ht, $wd) = (24, 60); for my $l (0 .. $ht - 1) { my $ou = " " x ($wd + 1); my($y0, $y1) = (2 * $l / $ht - 1, 2 * ($l + 1) / $ht - 1); my($su0, $su1) = (asin($y0), asin($y1)); for my $br (0 .. $p_m - 1) { for my $sgn (0, 1) { my($u0, $u1) = ($br * 2 * pie + $sgn * pie + $su0 * ($sgn?-1:1), +$br * 2 * pie + $sgn * pie + $su1 * ($sgn?-1:1)); my($v0, $v1) = ($u0 / $p_m * $p_n + $p_d, $u1 / $p_m * + $p_n + $p_d); my($x0, $x1) = (sin($v0), sin($v1)); $x1 < $x0 and ($x0, $x1) = ($x1, $x0); int(($v0 - pie / 2) / 2 / pie) == int(($v1 - pie / 2) +/ 2 / pie) or $x1 = 1; int(($v0 + pie / 2) / 2 / pie) == int(($v1 + pie / 2) +/ 2 / pie) or $x1 = -1; my($p0, $p1) = (($x0 + 1) / 2 * $wd, ($x1 + 1) / 2 * $ +wd); my ($ps, $pd) = int($p0) < int($p1) ? (int($p0), int($p1) - int($p0)) : (int(($p0 + $p1 + 1) / 2), 1); substr($ou, $p0, $pd) =~ y/ /*/; } } print $ou, "\n"; } } # -log(r)/p = x for (0 .. 19) { print "\n" x 4; my $r = sub { int(1 - log(1-rand(0.999)) / $_[0]) }; my($m, $n) = (&$r(0.7), &$r(0.9)); liss $m, $n, rand(2*pie); sleep 3; } __END__

      Update: I just want to mention that a classmate of mine has told me some years ago that you can render conic sections fast this way. This program uses basically the same algorithm except that it uses trigonometric functions instead of just square root. (Update: Yeah, except that this one is also cheating: where it says (p0+p1)/2, it should really use the p for (x0+x1)/2 really.)

      Update: posted changed version at Lissajous curves

      Nice effect. Reminds me of lissajous from my Basic days...

      I didn't know that particular program, in fact I've managed to (almost) always stay away from Basic but of course I'm familiar with Lissajous figures, which I also considered, although those would have required either ANSI sequences (and then are nice to be seen while being drawn - I wanted something to paste into email instead) or mangling with a buffer, whereas my program is both much simpler and gives me what I wanted, that is a potentially very long output. Lissajous figures by contrast are always constrained in a rectangle (if you don't consider rescaling, a square).