in reply to Re^9: Why does my get_max_index function return zero? (High Water Mark Algorithm)
in thread Why does my get_max_index function return zero? (High Water Mark Algorithm)

So, there seems to be multiple problems with holli's code

  1. Because the .. flip-flop holds its state between calls to the function, if you run holli's function twice with the same data set, the second will always fail.
  2. It seems that because the "if" conditional inhibits when the flip-flop increments its counter, there are many (most) situations where it won't work.
    • As AnomalousMonk pointed out here, data sets like (1,2,13,4,5, 99) don't work: this is because the "if" only triggers twice, on 13 and 99. (On first reading, or even second, I hadn't realized AnomalousMonk was trying to show a data set that didn't work; I hadn't understood the point that was being made, and I misinterpreted it as a counterpoint to what Marshall said, rather than an example of data that failed the algorithm)
    • If the data were (1,0,13,4,5) instead, it wouldn't have worked either, because the if didn't trigger on the 0, so the flip-flop hits 1 with 13, rather than 2.

The only way that the flip-flop will work as the counter is if the FF is run every time, but imax only increased sometimes... and then the ff shows off-by-one, because it starts at 1, so you have to correct for that. And my solution involved a separate variable to hold the ff state, which means it would have been better to just use a counter-variable to begin with. And my variant still doesn't solve the problem of multiple calls not resetting the ff state.

here's some example code which shows some of those above:

use strict; use warnings; use Test::More; $| = 1; sub holli { my $imax = 0; foreach (@_) { $imax = ($0 .. !$0) if $_ > $_[$imax]; } return $imax; } is( holli(1,2,13,4,5), 2, "holli(1,2,13,4,5): seems to work"); is( holli(1,2,13,4,5), 2, "holli(1,2,13,4,5): except that if you run i +t a second time, it will fail, because ff holds its state from last i +nstance"); is( do{local @_ = (1,2,13,4,5); my $imax=0; foreach(@_){$imax = ($0..! +$0) if $_>$_[$imax]}; $imax }, 2, "do(1,2,13,4,5): same data set, but + use a local do{} instead of the function to avoid the again bug"); is( do{local @_ = (1,2,13,4,5,99); my $imax=0; foreach(@_){$imax = ($0 +..!$0) if $_>$_[$imax]}; $imax }, 5, "AnomalousMonk(1,2,13,4,5,99): t +his data set fails, I think because"); is( do{local @_ = (3,2,1,3,2,1,3,2,1,15); my $imax=0; foreach(@_){$ima +x = ($0..!$0) if $_>$_[$imax]}; $imax }, 9, '(3,2,15): should be 9, b +ut is 1, because ff-if-cond only triggers once'); is( do{local @_ = (1,0,13); my $imax=0; foreach(@_){$imax = ($0..!$0) +if $_>$_[$imax]}; $imax }, 2, "do(1,0,13): second element is lower ra +ther than higher than first, so third is the first time that if-then- +ff triggers"); is( do{local @_ = (1,0,13,4); my $imax=0; foreach(@_){$imax = ($0..!$0 +) if $_>$_[$imax]}; $imax }, 2, "do(1,0,13,4): you would think this w +ould fail, too... but because \$_=4 happens to be greater than \$_[\$ +imax]=\$_[1]=0, it fakes it into passing, because of where values end +ed up."); ### here's my updated algorithm, to fix the couting errors and off-by- +one, but it does not fix the hold-state-between-runs ### ### also, note, I couldn't come up with a way to run the flipflop ever +y time, but assign to imax only on conditional, without storing the f +f result in a separate counter... in which case, the counter-based lo +ops make more sense than a flipflop anyway. is( do{ local @_ = (1,2,13,4,5); my $imax=0; foreach(@_){my$ff = $0 .. + !$0; $imax = $ff-1 if $_ > $_[$imax]}; $imax;}, 2, "pryrt: do(1,2,13 +,4,5)" ); is( do{ local @_ = (1,2,13,4,5,99); my $imax=0; foreach(@_){my$ff = $0 + .. !$0; $imax = $ff-1 if $_ > $_[$imax]}; $imax;}, 5, "pryrt: do(1,2 +,13,4,5,99)" ); is( do{ local @_ = (3,2,1,3,2,1,3,2,1,15); my $imax=0; foreach(@_){my$ +ff = $0 .. !$0; $imax = $ff-1 if $_ > $_[$imax]}; $imax;}, 9, "pryrt: + do(3,2,1,3,2,1,3,2,1,15)" ); is( do{ local @_ = (1,0,13); my $imax=0; foreach(@_){my$ff = $0 .. !$0 +; $imax = $ff-1 if $_ > $_[$imax]}; $imax;}, 2, "pryrt: do(1,0,13)" ) +; is( do{ local @_ = (1,0,13,4); my $imax=0; foreach(@_){my$ff = $0 .. ! +$0; $imax = $ff-1 if $_ > $_[$imax]}; $imax;}, 2, "pryrt: do(1,0,13,4 +)" ); done_testing();

  • Comment on Re^10: Why does my get_max_index function return zero? (High Water Mark Algorithm)
  • Download Code