randomfox: (Default)
[personal profile] randomfox
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>

Profile

randomfox: (Default)
randomfox

November 2012

S M T W T F S
    123
45678910
11121314151617
18192021222324
25262728 2930 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 11th, 2026 11:22 am
Powered by Dreamwidth Studios