Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Task:

You are an amazing programmer and Stackoverflow-answerer, and you decide to answer every question with a bounty on Stackoverflow. You are so good, that you manage to get all the bounties in all the questions. While you wait for the rep to come flooding in, you write a program that goes and find out what the total amount of rep is in all those bounties.

Rules:

  • When run,
    • Your program will navigate through the featured tab on Stack Overflow.
    • It will scrape out the value of each bounty,
    • Then it will add it up and display the total
  • It has to download data from anywhere on SO (and only SO), but I would recommend using http://stackoverflow.com/questions?pagesize=50&sort=featured , as it is only about 10 pages
  • This is , so the shortest code wins
share|improve this question
28  
cough api.stackexchange.com/docs/featured-questions cough –  bazzargh Mar 31 at 23:15
2  
stackoverflow.com/?tab=featured. All featured questions on 1 page. –  Nate Kerkhofs Apr 1 at 7:26
7  
@NateKerkhofs that's not all of them. Scroll to the bottom. eg when I just loaded it, it was showing 96 of 472 questions. –  bazzargh Apr 1 at 14:41
    
Bounty API –  justhalf Apr 3 at 3:21
    
@justhalf already been discussed... –  TheDoctor Apr 3 at 3:49

17 Answers 17

up vote 18 down vote accepted

JavaScript - 176 133 130 108 106

function f()(t+=$("[title~=an]").text(),u=$("[rel*=x]")[0])?$("html").load(u.href,f):alert(eval(t));f(t=0)

Edit 1: trimmed some selectors down and used the ?: suggestion from Google's Closure Compiler (via @Sirko - thanks)

Edit 2: initialise s inside d and initialise t as 0 instead of ""

Edit 3: realised I don't actually need to target a specific container and can sweep the whole document, which gets rid of a bunch of .find calls and an unnecessary selector (plus the variable holding it)

Edit 4: shove the t initialiser in the function call to avoid a ; (it'll get hoisted to the top anyway) and squash the function down to one statement (combine two statements into one inside the ternary statement condition) to drop the {}

Note: I'm not sure if it's cheating, but this has to be run from a console window of a browser already pointing at http://stackoverflow.com/questions?page=1&sort=featured. It relies on the fact that jQuery and the appropriate paging links are available on the page itself. Also, it only appears to work in Firefox and not in IE or Chrome.

Output (at time of posting):

38150 (in an alert dialog)

Exploded/commented:

function f()
    //concat all the bounty labels to t (they take the format "+50")
    //happens to be elements with title attribute containing word 'an'
    (t+=$("[title~=an]").text(),
    //find the "next" (has rel=next attribute) button
    u = $("[rel*=x]")[0])       
        ?
        //if there is a next button, load it, and then recurse f again
        $("html").load(u.href,f)
        :
        //else eval the 0+a+b+...+z tally and alert the result
        alert(eval(t))
//kick off the initial scrape (and simultaneously init the total tally)
f(t=0)
share|improve this answer
    
s=" #mainbar";d=$(s);t="";function a(){d.find(".bounty-indicator").each(function(){t+=this.innerHTML});(u=d.find("[‌​rel=next]")[0])?d.load(u.href+s,a):alert(eval(t))}a(); 169 - used Google Closure Compiler. –  Sirko Apr 1 at 7:17
7  
Sneaky choice of language and context to bypass a lot of the required characters! (Such as "stackoverflow.com/") I like it! –  AlexC Apr 1 at 9:30
    
I think you should mention that it is done using jQuery plugin. which I think it should be.. :) –  Mr_Green Apr 3 at 12:08
    
Chrome throws a syntax error. Opening a function body with a ( paren, does that really work? –  thejh Apr 3 at 13:01
    
@Mr_Green - I already noted that, but I've bolded it to draw more attention... –  Alconja Apr 3 at 23:22

Python - 232, 231, 195, 183, 176, 174

Parses the HTML from http://stackoverflow.com/questions?sort=featured using regular expressions.

The upper bound of range in the for loop must be number of pages + 1 or else the code will raise HTTPError because of 404s. Default number of results per-page is 15, which is what the code uses (omitting ?pagesize=50 saves on characters and is just as effective).

Thanks to @Gabe for the tip on reducing char count even further.

Golfed:

import requests,re;print sum(sum(map(int,re.findall(r"<.*>\+(\d+)<.*>",requests.get("http://stackoverflow.com/questions?sort=featured&page=%u"%i).text)))for i in range(1,33))

Output (at time of posting):

37700

Un-golfed:

Here's a somewhat un-golfed version that should be a bit easier to read and understand.

import urllib, re

print sum(
        sum(
            map( int,
                 re.findall( r"<.*>\+(\d+)<.*>",
                             urllib.urlopen( "http://stackoverflow.com/questions?sort=featured&page=%u" % i ).read()
                )
            )
        ) for i in range( 1, 33 )
    )
share|improve this answer
1  
You can get rid of the explicit for loop and get it down to 176: import urllib,re;print sum(sum(map(int,re.findall(r"<.*>\+(\d+)<.*>",urllib.urlopen("http://stackoverfl‌​ow.com/questions?sort=featured&page=%u"%i).read())))for i in range(1,33)) –  Gabe Apr 1 at 7:58
    
having a hardcoded upper bound makes it a little difficult to test –  Einacio Apr 1 at 12:50
2  
oh god –  WChargin Apr 2 at 0:27
5  
@Richard Yeah, but this is code golf, so brevity trumps whether it's a "good idea". I mean, in Real Life it's also not a good idea to write horrendous one-liners with no whitespace... –  Tim Goodman Apr 2 at 14:51
3  
@Richard Parsing html and extracting from html are pretty different tasks. Since a website is not a stable API, nothing is guaranteed to work for this kind of extraction. Though Tony's code is a bit overgolfed, so it'd fail if there is any tag containing a + followed by a number. For example a question title could fit that format. –  CodesInChaos Apr 2 at 15:18

Rebol - 164 133 130 (139 with 404 check)

Parses the html using the parse sub-language of Rebol. Checks the first 98 pages. I realised I have the same constraint as the python solution - too many repeats hit 404 errors and stop the execution. Thanks to @rgchris for many improvements! Updated to check up to 98 pages.

s: 0 repeat n 99[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]s

With error checking for 404s (139):

s: 0 repeat n 99[attempt[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]]s

Test

>> s: 0 repeat n 20[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]s
== 23600

>> s: 0 repeat n 99[attempt[parse read join http://stackoverflow.com/questions?sort=featured&page= n[15[thru{>+}copy x to{<}(s: s + do x)]]]]s
Script: none Version: none Date: none
== 36050

Explanation

Rebol ignores whitespace, hence you can put it all on one line like that if you choose. PARSE takes two inputs, and the first argument (read join ...) is fairly self-explanatory. But here are some comments on the parse dialect instructions, in a more traditional indentation:

s: 0
repeat n 99 [
    parse read join http://stackoverflow.com/questions?sort=featured&page= n [
        ;-- match the enclosed pattern 15 times (the rule will fail politely when there are less entries)
        15 [
            ;-- seek the match position up THRU (and including) the string >+
            thru {>+}
            ;-- copy contents at the current position up TO (but not including) <
            copy x to {<}
            ;-- (Basically, run some non-dialected Rebol if this match point is reached) the do is a bit dangerous as it runs the string as code
            (s: s + do x)
        ]
    ]
]
;-- evaluator returns last value, we want the value in S
;-- (not the result of PARSE, that's a boolean on whether the end of input was reached)
s
share|improve this answer
    
Nice...I added an oridinary formatted version with some comments, hope you don't mind! It's always great to see how well Rebol nails so many problems with such literacy (all in a half-meg cross-platform Apache-licensed executable but that makes things like REFORM stick out like a sore thumb Every other bit makes sense but I still look at that word and go "REduce and FORM being turned into REFORM" is just ugly. Obsessing over it is very Hawthorne. Oh, and you could change SOME to ANY and shave off a char! :-) –  Dr. Rebmu Apr 1 at 18:17
    
Oops, should be 133. –  rgchris Apr 2 at 2:56
    
Note: You need to loop to a higher n value... there's currently 28 pages of bounties (for page size 15). Won't impact your char count though. –  Alconja Apr 3 at 23:42
    
Thanks Alconja. Easy to go up to 98 pages before adding any more chars to the solution. I'll have to re-run the test from home tonight –  johnk Apr 4 at 0:51

Ruby, 260

require'open-uri'
require'zlib'
i=b=0
d=''
until /"has_more":f/=~d
i+=1
d=Zlib::GzipReader.new(open("http://api.stackexchange.com/2.2/questions/featured?site=stackoverflow&page=#{i}&pagesize=100")).read
b+=d.scan(/"bounty_amount":(\d+)/).map{|x|x[0].to_i}.reduce :+
end
p b

Uses the Stack Exchange API.

Output (as of time of original post):

37200

I'm not counting the &pagesize=100 in the character count, because it works without it, but I just added that for convenience while testing. If you remove that, it does the same thing (except it eats more quota and takes slightly longer).

share|improve this answer
    
Nice, I only got it to 275 in Python –  Claudiu Apr 1 at 3:08
    
eats more quota??? You were supposed to use the SO and SO only. –  Jan Dvorak Apr 3 at 13:51
    
@JanDvorak ??? I meant API quota. –  Doorknob Apr 3 at 15:10

Rebmu - 108107

rtN99[parseRDrj[http://stackoverflow.com/questions?sort=featured&page=N][15[thru{>+}copyXto{<}(a+JdoX)]]]j

Test (at 19:05 AEST)

>> rebmu [rtN99[parseRDrj[http://stackoverflow.com/questions?sort=featured&page=N][15[thru{>+}copyXto{<}(a+JdoX)]]]j]
Script: none Version: none Date: none
== 79200

Rebmu looks rather cryptic, but it is quite readable once you get the hang of it. Let's start by unmushing it and laying it out properly.

rt n 99 [
    parse rd rj [
        http://stackoverflow.com/questions?sort=featured&page= n
    ][
        15 [
            thru {>+}
            copy x to {<}
            (a+ j do x)
        ]
    ]
]
j

Rebmu is a dialect of Rebol so you can see the similarities in the solution. Rebmu can't reduce the size of every statement yet, but it is an evolving language. Thanks again to @rgchris for the improvements to my first attempt.

share|improve this answer
    
ti (to integer!) would be safer than do in Rebmu with no change in code length. –  rgchris Apr 3 at 12:19

PHP, 134, 131

<?
while($q=array_sum(preg_filter('#.*>\+#','',file("http://stackoverflow.com/questions?sort=featured&page=".++$n))))$s+=$q;echo$s;

Will loop through all pages, pagesize is not set to save bytes so more GETs.

Very Very Dirty, but... taking advantage of PHP's "flaws" !

  • no space after echo
  • while stops at asignment
  • output after regex replace is a string starting with the bounty amount
  • array_sum adds up strings
  • $n and $s not initialized, but starting from nothing is starting from zero
  • etc.
share|improve this answer

Bash 206

optimizations possible, too lazy

s=0;for i in `seq 1 11`;do for j in `wget -q -O - "http://stackoverflow.com/questions?pagesize=50&sort=featured&page=$i" | grep -o -E "bounty worth [0-9]*" | grep -o -E "[0-9]*"`;do s=$(($s+$j));done;done;echo $s

result:

39450
share|improve this answer
3  
I could be wrong, but this looks like it could be very short with some quality optimizations. –  br1ckb0t Apr 2 at 11:43
    
seq 1 11 can be reduced to seq 11. –  fedorqui Apr 2 at 20:00
    
You should be able to get rid of the spaces around pipes to save four chars, and surely those two greps can be merged into one (did you mean "[0-9]+"?). –  Desty Apr 3 at 9:27
    
Also "grep -o -E" => "egrep -o". –  Desty Apr 3 at 10:22
    
And you can change: "egrep -o '[0-9]+'" => "cut -d' ' -f3" :) –  Desty Apr 3 at 10:32

Ruby - 197

Short version:

require 'nokogiri'
require 'open-uri'
s=0
(1..33).each{|p|Nokogiri::HTML(open("http://stackoverflow.com/questions?page=#{p}&sort=featured")).css('.bounty-indicator').each{|b|s+=b.content.to_i}}
p s

Human friendly version:

require 'nokogiri'
require 'open-uri'
s=0
(1..33).each do |p|
    Nokogiri::HTML(open("http://stackoverflow.com/questions?page=#{p}&sort=featured")).css('.bounty-indicator').each do |b|
        s += b.content.to_i
    end
end
puts s

And answer - 39700

Ruby with script parameters - 139

require 'nokogiri'
require 'open-uri'
s=0
(1..33).each{|p|Nokogiri::HTML(open(ARGV[0]+p.to_s)).css(ARGV[1]).each{|b|s+=b.content.to_i}}
p s

To run this from bash just type

ruby code_golf_stack_overflow2.rb http://stackoverflow.com/questions?sort=featured\&page= .bounty-indicator
share|improve this answer

Javascript - 129 119 110 107 characters

EDIT: INVALID ANSWER! This only handles the "Top featured questions", which only has a fraction of them. Alconja's answer is more valid.

s="#mainbar";t="";eval("$(s).find('.bounty-indicator').each(function(){t+=this.innerHTML});alert(eval(t))")

Execute on http://stackoverflow.com/?tab=featured in a console window. Based on the solution by Alconja.

Golfed it a bit more by removing unneeded whitespaces.

Used eval to remove the function call, clearing another 9 characters.

cleared out some more unneeded whitespace.

share|improve this answer

PHP - 121 bytes

<?for(;preg_filter('/>\+(\d+)/e','$t+=\1',@file('http://stackoverflow.com/questions?sort=featured&page='.++$n)););echo$t;

Using a regex 'eval' modifier, to avoid using array_sum or similar. Seems to be the shortest solution among valid entries.

share|improve this answer
3  
the e modifier has been deprecated as of PHP 5.5, but it is still useful for golfing nonetheless. –  Fabrício Matté Apr 3 at 4:57

Java, 540 chars

Warning: the number of active bounties is ~470. This code will access a page on stackoverflow that many times. It may get you in trouble with them for making so many data requests.

import java.io.*;import java.net.*;public class B{public static void main(String[]A){String u="http://stackoverflow.com/questions",d;Long i,s=i=0L,n=i.parseLong(o(u).replaceAll("^.*b.>(\\d+).*$","$1"));while(i++<n){d=o(u+"?pagesize=1&sort=featured&page="+n).replaceAll("^.*ion.>.(\\d+).*$","$1");s+=d.matches(".*\\D.*")?0:n.parseLong(d);}System.out.print(s);}static String o(String s){String d="";try{BufferedReader r=new BufferedReader(new InputStreamReader(new URL(s).openStream()));while((s=r.readLine())!=null)d+=s;}finally{return d;}}}

My output was 23400, but when I ran @TonyH's code, I got 37550. Bad news.

Pretty code:

import java.io.*;
import java.net.*;

public class StackOverflowBounty {

    public static void main(String[] args) {
        String u = "http://stackoverflow.com/questions", d;
        Long i, s = i = 0L, n = i.parseLong(o(u).replaceAll("^.*b.>(\\d+).*$", "$1"));
        while (i++ < n) {
            d = o(u + "?pagesize=1&sort=featured&page=" + n).replaceAll("^.*ion.>.(\\d+).*$", "$1");
            s += d.matches(".*\\D.*") ? 0 : n.parseLong(d);
        }
        System.out.print(s);
    }

    static String o(String s) {
        String d = "";
        try {
            BufferedReader r = new BufferedReader(new InputStreamReader(new URL(s).openStream()));
            while ((s = r.readLine()) != null) {
                d += s;
            }
        } finally {
            return d;
        }
    }
}

The way this works is simple. It reads from the url http://stackoverflow.com/questions" to determine the number of questions that have bounties (note: if the number increases, the program fails, but if it drops, it works fine). It searches for this number using the regex: b.>(\\d+). This has worked in all tests to date, but if someone asked a question that matches that regex, this might not work.

Then, we open the url http://stackoverflow.com/questions?pagesize=1&sort=featured&page= + current question #. In other words, we open a new page for each featured question, and force the number of questions to be only 1, so we will get them all. The reputation part will always match ion.>.(\\d+), so I use that to find it. I split the operation into two parts so that I could cheaply check if the number of questions reduced (ie the string returned is not an integer).

Then, we sum up all the reputation and print it.

It took about 3 minutes and 20 seconds to run on my machine.


Does anyone know why it isn't printing the right number?

share|improve this answer
    
pagesize=100 gives the large number. I think something weird is happening because you're passing pagesize=1. In my answer, if i didn't specify 'pagesize', the result was close to your number. –  malik Apr 1 at 5:31
    
@malik Yeah I realized that I "misread" your comment, so I deleted mine :-). pagesize=100 acts as if pagesize=50. Did you mean that you ran my code with pagesize=100? –  Quincunx Apr 1 at 5:34

C# - 407

class B{void Main(string[] a){var o=0;for(int i=1;i<11;i++){var r=((System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(new Uri(string.Format(a[0]+"&page={0}",i)))).GetResponse();if(r.ContentLength>0){using(var s=new StreamReader(r.GetResponseStream()))foreach(Match m in Regex.Matches(s.ReadToEnd(),"bounty worth (.+?) "))o+=int.Parse(m.Value.Substring(m.Value.IndexOf('h')+2));}}Console.Write(o);}}

Using Stackoverflow.com. Same as below, except no Gzip decompressing and different regex.

Test

> prog.exe http://stackoverflow.com/questions?pagesize=50&sort=featured
38150

Weirdly, getting a different value than below.


C# - 496

This uses api.stackexchange which is gzipped and json.

using System.IO.Compression;class B{void Main(string[] a){var o=0;for(int i=1;i<11;i++){var r=((System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(new Uri(string.Format(a[0]+"&page={0}",i)))).GetResponse();if(r.ContentLength>0)using(var s=new StreamReader(new GZipStream(r.GetResponseStream(),CompressionMode.Decompress)))foreach(Match m in Regex.Matches(s.ReadToEnd(),@"bounty_amount"":(.+?),"))o+=int.Parse(m.Value.Substring(m.Value.IndexOf(':')+1).Replace(",",""));}Console.Write(o);}}

Unminified:

using System.IO.Compression;

class B
{
    void Main(string[] a)
    {
        var o = 0;
        for (int i=1; i<11; i++) {
            var w = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(new Uri(string.Format(a[0]+"&page={0}",i)));
            if(w.GetResponse().ContentLength > 0)
                using(var s = new StreamReader(new GZipStream(w.GetResponse().GetResponseStream(),CompressionMode.Decompress)))
                    foreach(Match m in Regex.Matches(s.ReadToEnd(), @"bounty_amount"":(.+?),"))
                        o += int.Parse(m.Value.Substring(m.Value.IndexOf(':')+1).Replace(",", ""));
        }
        Console.Write(o);
    }
}

Test

Default pagesize:

> prog.exe http://api.stackexchange.com/2.2/questions/featured?site=stackoverflow
25300

Pagesize=100:

> prog.exe "http://api.stackexchange.com/2.2/questions/featured?site=stackoverflow&pagesize=100"
37400
share|improve this answer

jQuery 191

i=0;function f(p){$.get('//api.stackexchange.com/2.2/questions/featured?site=stackoverflow&page='+p,function(d){for(x in d.items)i+=d.items[x].bounty_amount;d.has_more?f(p+1):alert(i)})};f(1)

It works from anywhere in stackexchange(and many other sites), no need to be in a specific page as in @Alconja/@NateKerkhofs answers

share|improve this answer
    
jQuery's a library, not a language. Not sure if it's valid or not... –  br1ckb0t Apr 2 at 11:44
    
@br1ckb0t take it as javascript if you like. jQuery is already on stackexchange sites anyways, I was just being explicit about the $ –  Einacio Apr 2 at 13:47
    
Yep, that makes sense! Nice code. –  br1ckb0t Apr 2 at 14:45

PHP - 139

Golfed:

<?php
$a=file_get_contents('http://stackoverflow.com/?tab=featured');preg_match_all('/n">\+([0-9]+)<\/div>/',$a,$r);echo array_sum($r[1]);

Ungolfed - 147

Simple file_get_contents / preg_match / array_sum

<?php
$a = file_get_contents('http://stackoverflow.com/?tab=featured');
preg_match_all('/n">\+([0-9]+)<\/div>/', $a, $r);
echo array_sum($r[1]);

Test:

php run.php

10250

share|improve this answer

Bash 174

Based on https://codegolf.stackexchange.com/a/25180/7664:

s=0;for i in {1..11};do for j in `wget -qO- "stackoverflow.com/questions?pagesize=50&sort=featured&page=$i"|cut -d' ' -f18|egrep '^[0-9]+$'`;do s=$(($s+$j));done;done;echo $s
share|improve this answer
    
You can get rid of the pagesize=50& and just loop more (I think the default page size if 15). –  Alconja Apr 3 at 23:46
    
@Alconja Hmm, right, so I could get this down to 162... but only with the downside of more request spam to the server. –  thejh Apr 4 at 8:12

Python (174 characters):

Expanding on the python answer above (don't have enough karma to comment):

import requests,re;print sum(sum(map(int,re.findall(r"<.*>\+(\d+)<.*>",requests.get("http://stackoverflow.com/questions?sort=featured&page=%u"%i).text)))for i in range(1,33))

Requests in lieu of urllib cuts down on 2 chars.

share|improve this answer

Ruby (176 chars):

Following Tony H.'s example of using hard-coded page numbers, here's what I got:

require'open-uri';b=0;(1..29).each{|i|d=open("http://stackoverflow.com/questions?sort=featured&page=#{i}").read;b+=d.scan(/<.*>\+(\d+)<.*>/).map{|x|x[0].to_i}.reduce 0,:+};p b

gave me 35300 at the time of writing.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.