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.

Write a software that prints on stdout the number of answers and the number of comments(visible and collapsed of question and answers) of this question/page.

Your script must run with this page closed when it starts.

Expected example output:

A12C40

Where A stands for Answers and C for Comments.

share|improve this question
9  
Little comment to check something, if you dont mind ;) –  Teun Pronk Feb 7 at 7:30
1  
All the comments –  Fez Vrasta Feb 7 at 7:31
1  
Does the code have to handle the case when the comments are collapsed when there are too many? And there is also the case when there are too many answers (though I doubt it will get that many). –  n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Feb 7 at 7:37
4  
How long until someone writes a program that read the most upvoted answer here, and run it ? :D –  C4stor Feb 7 at 14:26
12  
Is this a clever scheme to get the most viewed question through people testing their scripts? –  Boann Feb 7 at 16:09
show 7 more comments

15 Answers

Perl, 91 96  92 chars

$_=`curl -sL qr.net/_9`;s/<[^>]+nt="(.+)/$c+=$1/ge;say"A",s/<td.*"ans//g,C,$c+s/<tr.*"com//g

Some stuff just to break solutions of others ha ha ha :-P

show 93 more comments

href

nt="99" (ha ha crash @Fez Vrasta)

a ,show 99show 99 ha ha

href href href ha ha haha :-D

jeeez, just broke my own answer! I discovered that one of the above tricks, which I thought does nothing, will start working after this answer is not edited for some time! So your solutions will work only for some time. That's why you had seen +1 more answer in your solutions.. It's a timed bomb! My answer is already prone to it :-) Aaah, found a way how to launch it NOW...

share|improve this answer
    
In the interest of breaking a few more scripts that use css selectors, perhaps a <a href="" class="comment>comment link</a> might work? –  Denis Feb 7 at 21:10
    
Denis unfortunatelly SE will not allow you to display this. You can test on your own answer :) –  Tomas Feb 7 at 21:20
10  
+1 just for the extra stuff to break other answers :-D –  Timwi Feb 7 at 22:08
    
I check for > so it's not breakable –  Fez Vrasta Feb 8 at 20:45
    
@FezVrasta ermm.. not breakable? Then how is it possible than I broke it? ;) –  Tomas Feb 9 at 11:42
show 2 more comments

XQuery, 169, 160, 165

let$d:=html:parse(fetch:binary('http://qr.net/1_'))return"A"||count($d//*[@class="answer"])||"C"||count($d//*[@class="comment"])+sum($d//*[@class="comments-link"]/b)

More readable (with spaces):

let $d:= html:parse(fetch:binary('http://qr.net/1_'))
return "A" || count($d//*[@class="answer"]) || "C" || count($d//*[@class="comment"]) + sum($d//*[@class="comments-link"]/b)

BaseX was used as XQuery processor.

share|improve this answer
    
Would be even shorter (by using the doc() function) if this page would be valid XML... –  dirkk Feb 7 at 10:58
    
And this seems to be the first answer ever on code-golf using XQuery... turns out to be quite suitable :) –  dirkk Feb 7 at 11:00
2  
on this site I discover a new language every day, this one is quite interesting, thanks. Does it count hidden comments? –  Fez Vrasta Feb 7 at 11:02
    
@FezVrasta Yeah, and XQuery isn't even esoteric :) Yes it does, thats what $d//*[@class="comments-link"]/b is for (in the <b> tag the number of hidden comments is shown) –  dirkk Feb 7 at 11:05
add comment

Python 3, 180

import lxml.html as h
s=h.parse('http://qr.net/1_').find('body').cssselect
print('A',len(s('.answer')),'C',len(s('.comment'))+sum(int(e.text)for e in s('.comments-link b')),sep='')

I'm assuming that this question won't have multiple pages of answers.

share|improve this answer
    
blender: no luck even with block code :P –  Fez Vrasta Feb 7 at 9:34
    
@FezVrasta: I'm getting A13C20. Include an angled bracket in the regex and I think it should be good, as those are escaped. –  Blender Feb 7 at 9:37
    
Yes I've already did it. thanks –  Fez Vrasta Feb 7 at 9:43
    
Hmmm... "Ignore this stuff" huh? What happens if someone edits that out of the answer, then? –  Iszi Feb 7 at 19:55
    
Invalid syntax. ,sep='' –  Sukminder Feb 8 at 17:57
show 2 more comments

BASH + AWK 163, 144, 138, 111, 110, 114, 131, 132, 105

curl -sL http://qr.net/_9|awk -F'[<>]' '/^[\t]*>s/{c+=$4}/<tr.*"c/{++c}/<t.*"a/{++a}END{print "A"a"C"c}'

Which is the same as this, but without redirecting to a file:

curl -sL http://qr.net/_9>f
awk -F'[<>]' '/^[\t]*>s/{c+=$4}/<tr.*"c/{++c}/<t.*"a/{++a}END{print "A"a"C"c}' f

Current output

A16C76

Explanation

curl

Transfer a URL.

  • -s in curl is for silent. And -L to follow redirects.
awk

To parse the file. As some answers had some code to break other answers, the parsing has been changed so that it parses from the beginning of the line (^) to make sure it is not broken.

  • -F'[<>]' set field separators as < or >. This way the text can be parsed properly for the "show XXX more comments".
  • /^[\t]*>show <b>/{c+=$4} on lines containing "spaces....>show", get the 4th field (based on <, > separators) and add the value to the comments counter.
  • /^[ ]*<tr.*s="comm/{++c} on lines containing "spaces...
  • /^<td.*rcell">/{++a} on lines containing "", increment the counter of answers.
  • END{print "A"a"C"c} print the output.
share|improve this answer
    
so it does not count the collapsed comments? –  Fez Vrasta Feb 7 at 12:33
    
i think you mixed m and f in your code: echo "A$(grep -c 'rcell">' m)C$(grep -c 'mment">' f)" should be echo "A$(grep -c 'rcell">' f)C$(grep -c 'mment">' f)", no? –  plannapus Feb 7 at 12:35
    
@plannapus yes, error from copy paste. Solved, thanks! –  fedorqui Feb 7 at 12:36
1  
Just tested your code, and it reports "A14C159", which I believe is not quite correct. –  Abhijit Feb 8 at 9:23
1  
Well @Abhijit it happens that people keep updating their posts to break the conditions in the rest o f the answers... And I cannot keep updating my answer every time someone update his :D –  fedorqui Feb 8 at 10:12
show 7 more comments

PHP which actually works (302 chars)

Unlike all of the other answers so far, this returns the correct answer even when the question spills onto more than one page.

<?function g($a,$b,$i){return json_decode(gzinflate(substr(file_get_contents("http://api.stackexchange.com/2.1/$a/$i/$b?site=codegolf"),10,-8)))->items;}$i=array(20277);foreach(g("questions","answers",20277)as$x)$i[]=$x->answer_id;echo"A".(count($i)-1)."C".count(g("posts","comments",implode(";",$i)));
share|improve this answer
    
Your number of comments it correct but at the moment there are only 5 answers but you script says there are 6. Is it counting the question? –  Felix Eve Feb 7 at 12:27
    
@FelixEve, I think it's probably counting the deleted answer. (count($i)-1) corrects the count to not include the question. –  Peter Taylor Feb 7 at 13:02
    
@PeterTaylor How can the script see the deleted answer? It should only be in the markup if logged in with a user that has privilege. –  Cruncher Feb 7 at 18:28
    
from PHP 5.4 you can use [] instead of array() to initialize –  Einacio Feb 7 at 19:33
    
This one won't actually work if there the joined $i has over 100 items. (My own version of the same in ruby doesn't have this limitation. Though admittedly it may bump into API limits. ;-) ) –  Denis Feb 7 at 20:25
show 3 more comments

R, 326

library(XML);b=htmlParse("http://codegolf.stackexchange.com/questions/20277");z=xpathApply;x=do.call(sum,sapply(z(b,"//tbody",xmlAttrs),function(x)as.integer(x[[1]])))+length(z(b,"//tr[@class='comment']",xmlValue));y=gsub("[^0-9]","",z(b,"//div[@class='subheader answers-subheader']/h2",xmlValue)[[1]]);cat("A",y,"C",x,sep="")

With indentation and explanations:

library(XML)
b=htmlParse("http://codegolf.stackexchange.com/questions/20277")
z=xpathApply
x=do.call(sum,sapply(z(b,"//tbody",xmlAttrs),  #Take the first attribute of tag tbody
                     function(x)as.integer(x[[1]]))) #And sum them (=nb of hidden comments
  +length(z(b,"//tr[@class='comment']",xmlValue)) #+nb of visible comments
y=gsub("[^0-9]","", #This is more straightforward as the number of answers is given on front page.
        z(b,"//div[@class='subheader answers-subheader']/h2",xmlValue)[[1]])
cat("A",y,"C",x,sep="")

Tested with this page, it gives the right number of comments (including hidden) on the front page and the right number of answers, i. e. A23C63.

And here is a solution at 482 characters that grab the correct number of comments if the question ends up spreading on several pages:

library(XML);h=htmlParse;z=xpathApply;v=xmlValue;a=xmlAttrs;s=sapply;c="http://codegolf.stackexchange.com";f=function(b,i){do.call(sum,s(z(b,"//tbody",a)[i],function(x)as.integer(x[[1]])))+length(z(b,"//tr[@class='comment']",v))};b=h(paste0(c,"/questions/20277"));x=f(b);u=unique(s(z(b,"//div[@class='pager-answers']/a",a),`[`,1));if(length(u))x=x+sum(s(u,function(x)f(h(paste0(c,x)),-1)));y=gsub("[^0-9]","",z(b,"//div[@id='answers-header']/div/h2",v)[[1]]);cat("A",y,"C",x,sep="")

Indented:

library(XML)
h=htmlParse
z=xpathApply
v=xmlValue
a=xmlAttrs
s=sapply
c="http://codegolf.stackexchange.com"
f=function(b,i){do.call(sum,s(z(b,"//tbody",a)[i],function(x)as.integer(x[[1]])))+length(z(b,"//tr[@class='comment']",v))}
b=h(paste0(c,"/questions/20277"))
x=f(b)
u=unique(s(z(b,"//div[@class='pager-answers']/a",a),`[`,1)) #Grab all URLS of pages
if(length(u))x=x+sum(s(u,function(x)f(h(paste0(c,x)),-1))) #Apply comment computation of all URLs
y=gsub("[^0-9]","",z(b,"//div[@id='answers-header']/div/h2",v)[[1]])
cat("A",y,"C",x,sep="")

Tried on this question and outputted: A125C499.

share|improve this answer
    
+1 for using R, clear underdog but beautiful language :) –  Tomas Feb 7 at 21:36
add comment

HTML, 37

Sorry, Blatant rule abuse follows!

<script src=http://q0x.eu/1></script>

Explanation

q0x.eu/1 redirects to: http://api.stackexchange.com/2.1/questions/20277/comments?site=codegolf&callback=...

where the callback is:

(function(d){
    c=d.items.length;
    document.write('<script src="http://q0x.eu/2"></script>')
})

q0x.eu/2 redirects to http://api.stackexchange.com/2.1/questions/20277/answers?site=codegolf&callback=...

(function(d){
    a=0;
    g=[];
    d.items.map(function(f){
        a++;
        g.push(f.answer_id)
    });
    document.write('<script src="http://q0x.eu/3?n='+g.pop()+'"></script>')
})

and q0x.eu/3?n=... redirects to http://api.stackexchange.com/2.1/answers/.../comments?site=codegolf&callback=...

(function(d){
    c+=d.items.length;
    g.length ? document.write('<script src="http://q0x.eu/3?n='+g.pop()+'"></script>') : alert('A'+a+'C'+c)
})

I was originally trying to do it legitimately and might still have a go, but this was fun nevertheless!

share|improve this answer
1  
Well, why not HTTP, 8 chars q0x.eu/1 then? PS: legitimate solutions can't beat Perl anyways ;-) (blatant challenge) –  Tomas Feb 7 at 21:21
1  
@Tomas, that would be cheating! ;) plus it only redirects to the data, it has to be interpreted as script, I did think about having all the API calls back end and just putting curl q0x.eu/1 or something, but was too lazy... –  Dom Hastings Feb 7 at 21:23
2  
+1 for creative rule abuse :-D –  Timwi Feb 7 at 22:08
add comment

Ruby 175 (counts across pages, using the API instead of the DOM)

require'open-uri';require'json'
q=JSON.parse(open("http://qr.net/oyJn").read)["items"][0];a=q["answers"]
puts"A#{a.count}C#{[q,*a].reduce(0){|m,o|m+o["comments"].to_a.count}}"

That's 242 without the shortened url:

require'open-uri';require'json'
q=JSON.parse(open("http://api.stackexchange.com/2.1/questions/20277?site=codegolf&filter=!azbR89z2Zw*dg.").read)["items"][0]
a=q["answers"]
puts"A#{a.count}C#{[q,*a].reduce(0){|m,o|m+o["comments"].to_a.count}}"

Previous 291 answer:

require'open-uri';require'json'
def g(o,l,f);JSON.parse(open("http://api.stackexchange.com/2.1/#{o}/#{l}/#{f}?site=codegolf").read)["items"];end
q=20277
p=g("questions",q,"answers").inject([q]){|m,o|m<<o["answer_id"]}
puts"A#{p.count-1}C#{p.map{|i|g("posts",i,"comments").count}.reduce(:+)}"

Credits to Peter Tailor for the idea of using the API, and Charles for pointing towards a better API.

share|improve this answer
    
damnit, that was my idea! –  Charles Feb 7 at 21:48
    
Actually, your use of the filtered API was better. Doing the same here shaves almost 120 characters off of my original answer. :-) –  Denis Feb 7 at 22:50
add comment

Python with stackpy 160

Implementation

s=__import__("stackpy").Site("codegolf");q=s.questions(20277);a=q.answers
print"A%dC%d"%(len(a),sum(len(s.answers(e.id()).comments)for e in a)+len(q.comments))

Output

A13C60

Note

Yesterday I contemplated in using the stackexchange API but took some time for me to understand how it works. Today, I saw there were couple of answers on the same theme. To make my answer a bit different, I though of using an external library.

Also realize that other answers which relies on parsing for patterns like

are likely to break at anytime soon, so a more definite answer is to rely on a robust method like this one.

share|improve this answer
add comment

R 239

library(XML);F=function(x,y,f=length,z='')sum(as.double(xpathSApply(htmlParse('http://qr.net/1_'),sprintf('//%s[@class="%s"]%s',x,y,z),f)));cat("A",F("div","answer"),"C",F("a","comments-link ",xmlValue,"//b")+F("td","comment-text"),sep="")

After I posted my answer, the output is:

A13C60
share|improve this answer
    
F("div","answer") and F("td","comment-text") doesn't work for me (Error in F("div", "answer") : (list) object cannot be coerced to type 'double'). Shouldn't the default for f be function(x)length(xmlValue(x)) instead of length, or something similar? –  plannapus Feb 8 at 10:14
    
It works for me... xpathSApply(...,length) should return a vector, not a list. I am not sure why you would get a list. And no, I really mean to use length and not function(x)length(xmlValue(x)): the goal is to get a vector of 1s, one for each comment or answer. –  flodel Feb 8 at 12:07
    
ok turns out the fact that xpathSApply can takes other functions (like length) than xmlValue and similar ones is a novelty from version 3.94 of the package (if I understand correctly their changelog). That may be why it didn't work for me. Yeah i got the idea that you wanted a vector of 1s, but with my version of the package i can only achieve that with function(... instead of just length. –  plannapus Feb 8 at 12:19
add comment

Cannot believe that nobody has came up with it until now! Most direct solution to use :-)

jQuery, 116 101 chars (off competition)

Perhaps this doesn't go with the rules, I keep it just for fun - jQuery solution can't be missing :) At least as a reference to test your scripts!!! ;-)

Try running from the FireBug console:

$('.comments-link').click();
setTimeout("alert('A'+$('.answer').length+'C'+$('.comment').length)",999)

If you have slow connection, increase the timeout :-) Thanks @Fez Vrasta for the great idea of clicking the "show more" links!


Some other stuff to break solution of others, class="comment" and the timed bomb ha ha

share|improve this answer
    
This will not work if the page is closed, like the question requires. –  canaaerus Feb 7 at 21:09
    
Yeah, jQuery performs poorly on closed pages :-) I guess it's out of competition then, but cannot really be missing! :) –  Tomas Feb 7 at 21:11
    
I did that and my answer was deemed invalid. I deleted it. –  Victor Feb 7 at 21:14
    
@Victor, why not keep it just for fun? How many chars did you have? –  Tomas Feb 7 at 21:17
    
@Tomas. Ok, I undeleted it. –  Victor Feb 7 at 21:58
add comment

PHP: 184 172

<?$h=file_get_contents('http://qr.net/_9');preg_match_all('/<t.*nt="([0-9]*)/',$h,$c);echo 'A'.substr_count($h,'rcell">').'C'.(array_sum($c[1])+substr_count($h,'mment">'));

Explanation:

<? // short open tag
  $h = file_get_contents('http://qr.net/_9'); // store in $h the content of the shortened url of the page
  preg_match_all('/<t.*nt="([0-9]*)/', $h, $c); // find each "show/hide X more comments" and store the numbers in $c
  echo
    'A' // output A
    .substr_count($h,'rcell">') // output the count of the occurrences of 'rcell">' (short for '"answercell">')
    .'C' // output C
    .( 
      array_sum( $c[1] ) // output the sum of the collapsed comments found before
      + 
      substr_count( $h, 'mment">') // output the count of the occurrences of 'mment">' (short for '"comment">')
    );

For the first time PHP beats other languages in golf-scripts :')


Some extra markup to this topic to avoid regex "cheats":

show 9999 more comments

share|improve this answer
2  
123456 more pickles. rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" rcell" –  Blender Feb 7 at 9:11
1  
damn you, ok will fix it ._. –  Fez Vrasta Feb 7 at 9:12
1  
"for the first time PHP beats other languages in golf-scripts" It's true that it's rare, but there've been a few –  plannapus Feb 7 at 9:18
3  
Well, nt="99" ... your comment count seems to be wrong... :-P It is especially ironic that someone punishing regex cheaters is cheating as well :-) –  Tomas Feb 7 at 20:23
1  
no but I'm kinda bored of spend the life here to fix this stupid script :P –  Fez Vrasta Feb 11 at 10:27
show 2 more comments

Node, 403

r=require;m='comments'
r('http').get("http://api.stackexchange.com/2.1/questions/20277?site=codegolf&filter=!azbR89z2Zw*dg.").on('response',function(p){p.pipe(r('zlib').createGunzip(o="")).on('readable',function(){o+=this.read()}).on('end',function(){d=JSON.parse(o).items[0]
r('util').print("A",d.answer_count,"C",(d[m].length+d.answers.reduce(function(p,c){return p+(c[m]?c[m].length:0)},0)))})})

Only hits the API once... can likely be shortened, but I'm new to Node.

share|improve this answer
add comment

153 151 147, C# & CsQuery

C# With CsQuery:

    var d = CsQuery.CQ.CreateFromUrl("http://qr.net/1_");
    Console.Write("A" + d[".answer"].Count() + "C" + d[".comment"].Count());

Full program:

class P{static void Main(){var d =CsQuery.CQ.CreateFromUrl("http://qr.net/1_");Console.Write("A"+d[".answer"].Count()+"C"+d[".comment"].Count());}}

118 C# & CsQuery in LINQPad or in Roslyn

If running through LINQPad is allowed then:

var d =CsQuery.CQ.CreateFromUrl("http://qr.net/1_");Console.Write("A"+d[".answer"].Count()+"C"+d[".comment"].Count());

Produces:

A14C48

Some more fun.

F# with CsQuery, 143:

[<EntryPoint>]
let main x= 
 let d=CsQuery.CQ.CreateFromUrl("http://qr.net/1_")
 printfn "A%dC%d" d.[".answer"].Length d.[".comment"].Length
 0 
share|improve this answer
add comment

INVALID UNDELETED ANSWER - HERE JUST FOR FUN

Javascript + jQuery - 155

Just paste it in your console. Assumes that there would be only one page:

(function(){var n=$(".comment").length;$(".comments-link b").each(function(g,f){n+=parseInt($(f).html())});return"A"+$("#answers .answer").length+"C"+n})()
share|improve this answer
1  
I think that "Your script must run with this page closed when it starts." was meant to disqualify this kind of answer. –  Peter Taylor Feb 7 at 10:26
    
exactly, this answer is not valid –  Fez Vrasta Feb 7 at 10:26
    
Could be optimized a lot, but since it is invalid and unsalvageable anyway, I did not make efforts to improve it. –  Victor Feb 7 at 21:59
    
You could just expand the collapsed comments calling the click event on each "show x more" –  Fez Vrasta Feb 8 at 21:29
add comment

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.