in reply to Re: Spreading out the elements
in thread Spreading out the elements

Unfortunately, it turns out that the Bresenham algorithm isn't exactly the right thing - or I've misconscrewed something. Here's my implementation of it, with extra code to detect the crossings; it does a reasonable distribution of the two arrays, but doesn't quite follow the rules that I originally stated:

#!/usr/bin/perl -w # Created by Ben Okopnik on Wed Jul 4 13:39:28 EDT 2007 # Modified and converted to code from Wikipedia entry for "Bresenham" sub brezzie { my ($x1, $y1) = @_; ($x1, $y1) = ($y1, $x1) if $y1 > $x1; my ($deltax, $deltay) = ($x1, $y1); my $error = -$deltax / 2; my $y = 0; my ($last_a, $last_b) = (0, 0); for my $x (0 .. $x1){ # print $steep ? "$y $x\n" : "$x $y\n"; if ($y1 > $x1){ ($b, $a) = ($x, $y); } else { ($a, $b) = ($y, $x); } print "A" if $a > $last_a; print "B" if $b > $last_b; ($last_a, $last_b) = ($a, $b); $error += $deltay; if ($error > 0){ $y = $y + 1; $error -= $deltax; } } } brezzie(4, 14);

Running this results in 'BABBBBABBBABBBBABB' - and what I'm looking for is more like 'ABBBBBABBBBABBBBBA'. Max distance is not quite the same thing as a fair distribution.

I really appreciate the help that you've given me so far!

Replies are listed 'Best First'.
Re^3: Spreading out the elements
by ForgotPasswordAgain (Vicar) on Jul 05, 2007 at 14:02 UTC

    I think this is what merlyn means:

    perl -MAlgorithm::Line::Bresenham=line -le'($A,$B)=@ARGV;@p=map{$_->[0 +]}line($A,1,1,$B);$l=$p[1];for(1..$B){if($p[$_]==$l){push@a,"A"}else{ +push@a,"B";$l=$p[$_]}}print$_ for@a' 10 40

    Sorry, made it on the command line, can't be bothered to reformat it. The idea is to use ($A, 1) for the start point, (1, $B) for the end point, then pluck out the x values (projection of line onto x-axis, if that makes sense) from the list returned by line. The x values will sometimes stay the same, sometimes increase; you're interested in where it increases, that's where the Bs get plopped in.

    I don't think that you'll generally have the exact right number of each element, just that you'll get a roughly even distribution of elements, given a certain ratio of A and B. Quickly experimenting about, I found that it breaks a little when the 1st number approaches the 2nd one (try 990 and 1000, for example, there will be 989 Bs instead of 990)

    Assumes: two integer args on command line, the first would be your number of Bs, the second the total number of A + B.

    It doesn't do things you wanted like endpoints always are A. For that, just subtract 2 from 2nd arg, and print out A at the beginning and end.