randomfox (randomfox) wrote,
randomfox
randomfox

Calculate bills and hits needed to add 1 to the George Score

The George Score at Where's George is based on the following formula:
GS = 100 * 
     (sqrt(log(BillsEntered)) + log(TotalHits + 1)) * 
     (1 - DaysInactive / 90)

This Perl script calculates how many bills you need to enter or how many hits you need to get to increase the George Score by 1. It does that two ways: by using derivatives and by solving the George Score equation.

#!perl -w
use strict;
require 5.004;

# Calculate george score.
# be = bills entered, th = total hits, di = days of inactivity
sub gs {
    my $be = shift;
    my $th = shift;
    my $di = shift;
    100 * (sqrt(log($be)) + log($th + 1)) * (1 - $di / 90);
}

# Takes a function with one argument.
# Uses linear interpolation to find out how large the function's argument
# must be to raise the function's value by 1.
sub solve1gs {
    my $fn = shift;

    my $cur_gs = $fn->(0);
    my $upper;    
    for ($upper = 1; $upper < 1e9; $upper *= 2) {
	last if $fn->($upper) - $cur_gs >= 1;
    }

    my $a = 0;
    my $b = $upper;
    my $itercount = 0;
    my $xold = $a;

    for (;;) {
	my $fa = $fn->($a) - $cur_gs - 1;
	my $fb = $fn->($b) - $cur_gs - 1;

	my $newx = $a - $fa * ($b - $a) / ($fb - $fa);
	my $newfx = $fn->($newx) - $cur_gs - 1;

	++$itercount;
	print "  $itercount: $newx $newfx\n";

	return $newx if abs($newx - $xold) < 1e-10 * abs($newx);
	$xold = $newx;

	if ($fa * $newfx > 0) {
	    $a = $newx;
	}
	else {
	    $b = $newx;
	}
    }
}

@ARGV >= 2 or die "Usage: $0 bills-entered total-hits [days-inactive]\n";

my ($be, $th, $di) = @ARGV;

defined $di or $di = 0;

print  "Bills Entered        = $be\n";
print  "Total Hits           = $th\n";
print  "Days Inactive        = $di\n";
printf "George Score         = %.3f\n", gs($be, $th, $di);
print "\n";

my $hitpred = ($th + 1) / 100;
my $billpred = $be * sqrt(log($be)) / 50;

printf "Hits needed for 1GS  = %.0f\n", $hitpred;
printf "Bills needed for 1GS = %.0f\n", $billpred;
printf "Bill/Hit ratio       = %.3f\n", $billpred / $hitpred;
print "\n";

$hitpred = solve1gs
    sub {
	my $incrhits = shift;
	gs($be, $th + $incrhits, $di);
    };

$billpred = solve1gs
    sub {
	my $incrbills = shift;
	gs($be + $incrbills, $th, $di);
    };

print "\n";
printf "Hits needed for 1GS  = %.2f\n", $hitpred;
printf "Bills needed for 1GS = %.2f\n", $billpred;
printf "Bill/Hit ratio       = %.3f\n", $billpred / $hitpred;

__END__

Example:
C:\temp>gs.pl
Usage: C:\temp\gs.pl bills-entered total-hits [days-inactive]

C:\temp>gs.pl 93460 26424
Bills Entered        = 93460
Total Hits           = 26424
Days Inactive        = 0
George Score         = 1356.515

Hits needed for 1GS  = 264
Bills needed for 1GS = 6324
Bill/Hit ratio       = 23.931

  1: 266.801812199827 0.00459382687245125
  2: 265.58177550269 2.28931100991758e-005
  3: 265.57569564905 1.14084741653642e-007
  4: 265.575665350918 5.68661562283523e-010
  5: 265.575665199896 2.72848410531878e-012
  6: 265.575665199171 0
  1: 6609.01652641187 0.00832274145204792
  2: 6554.46540548562 0.000287633121843101
  3: 6552.58066625246 9.93870207821601e-006
  4: 6552.51554275262 3.4341360333201e-007
  5: 6552.51329253042 1.18661773740314e-008
  6: 6552.51321477713 4.09954736824147e-010
  7: 6552.5132120909 1.43245415529236e-011
  8: 6552.51321199704 4.54747350886464e-013

Hits needed for 1GS  = 265.58
Bills needed for 1GS = 6552.51
Bill/Hit ratio       = 24.673

C:\temp>

Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments