16
\$\begingroup\$

Introduction

Sometimes I get bored and there are no new questions on PPCG, so I want you to dig a random question from PPCG's past.

Challenge

Given a user's PPCG ID as input (e.g. my ID is 30525), output the URL of a randomly chosen PPCG question. If the question does not meet the following criteria, you must choose another question until it does meet the criteria:

  • The question asker must not be the user whose ID was inputted to the question
  • The question must not have already been answered by the user whose ID was inputted to the question
  • The question must not be unanswered: it's probably too hard
  • The question must not have over 10 answers: it's probably too easy
  • The question must be tagged

Rules

URL shorteners are disallowed.

You may use the Stack Exchange API and the Stack Exchange Data Explorer.

You will only ever be given a real PPCG user's ID.

In the unlikely event that there are no suitable questions, you do not have to output anything (undefined behaviour is fine).

Side Challenge

Although you won't be awarded extra points, it would be appreciated if someone designed a usable bookmarklet which, when run, opened the browser window to a random PPCG question that follows the above criteria. The user ID should be hardcoded into program (for the bookmarklet only).

Challenge

The shortest code in bytes wins.

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

JavaScript (ES6), 333 329 327 323 283 bytes

Needs to be run from within the api.stackexchange.com domain (relevant meta). Returns a Promise containing the URL (relevant meta).

f=async i=>await(u="/questions/",s="?tagged=code-golf&site=codegolf",q=await(await(await fetch(u+s)).json()).items.filter(x=>x.owner.user_id!=i&x.answer_count<11).sort(_=>.5-Math.random())[0],await(await fetch(u+q.question_id+s)).json()).items.some(x=>x.owner.user_id==i)?f(i):q.link

Try it

f=async i=>await(u="//api.stackexchange.com/questions/",s="?tagged=code-golf&site=codegolf",q=await(await(await fetch(u+s)).json()).items.filter(x=>x.owner.user_id!=i&x.answer_count<11).sort(_=>.5-Math.random())[0],await(await fetch(u+q.question_id+s)).json()).items.some(x=>x.owner.user_id==i)?f(i):q.link
k.previousSibling.value=58974 // me
k.onclick=_=>f(+k.previousSibling.value).then(p=>k.nextSibling.innerText=p)
<input type=number><button id=k>Fetch</button><pre>


Bookmarklet

And here it is as a customisable bookmarklet, which will load a random question you've yet to answer. To use it, simply add a new bookmark to your browser's toolbar and drop the full code into the URL field.

Unlike the above solution, this works with all questions on a site therefore it may be slow to run (depending on the site and tags) and could also be expensive in the number of queries it needs to make to the API, as the API can only return 100 questions at a time.

To customise, change the following variables

  • k: Your API key - you can register for one here.
  • s: The Stack Exchange site you want to grab a question for.
  • i: Your user ID on that site.
  • t: The tags you want to filter by. There are 4 options available for this one:
    1. "": An empty string; if you don't want to filter by any tags,
    2. "code-golf;string": A semi-colon separated list of tags you want to filter by,
    3. prompt("Tags:"): You will be prompted to enter the tags you want to filter by, or,
    4. prompt("Tags:","code-golf;string"): You will be prompted to enter the tags you want to filter by, with a default list provided.
javascript:(f=(

/* See https://codegolf.stackexchange.com/a/122400/58974 for documenation */
k="",
s="codegolf",
i=58974,
t="code-golf",

p=1,q=[],r=1)=>fetch((u="//api.stackexchange.com/questions/")+(d=`?key=${k}&tagged=${t}&site=`+s)+`&page=${p}&pagesize=100`).then(r=>r.json()).then(j=>r&&(q=[...q,...j.items.filter(x=>x.owner.user_id!=i&(a=x.answer_count)&a<11)])^j.has_more?f(i,k,s,t,p+1,q,1):q.sort(_=>.5-Math.random())[0]).then(y=>fetch(u+y.question_id+"/answers"+d).then(r=>r.json()).then(j=>j.items.some(x=>x.owner.user_id==i)?f(i,k,s,t,q,0):window.location=y.link)))()
\$\endgroup\$
13
  • 1
    \$\begingroup\$ based my powershell answer on this one, nice reuse of the strings for the api. \$\endgroup\$
    – colsw
    Commented May 24, 2017 at 10:47
  • \$\begingroup\$ At which point do you get banned permanently? ;) \$\endgroup\$
    – Beta Decay
    Commented May 24, 2017 at 11:13
  • \$\begingroup\$ @BetaDecay, if the API challenges pick up pace again, I might soon find out! :D \$\endgroup\$
    – Shaggy
    Commented May 24, 2017 at 11:14
  • \$\begingroup\$ You can use the api tokens from here: stackapps.com/q/7384/45852 to increase your rate limit. \$\endgroup\$
    – user58826
    Commented May 24, 2017 at 13:57
  • 1
    \$\begingroup\$ @BetaDecay, I did intend on expanding it into a usable script but ran out of time; I'll try to come back to it tomorrow. \$\endgroup\$
    – Shaggy
    Commented May 24, 2017 at 19:31
4
\$\begingroup\$

PowerShell, 261 Bytes

param($i)$q=irm (($u="api.stackexchange.com/questions/")+($s="?tagged=code-golf&site=codegolf"))
do{$t=$q.items|?{$c=$_|% an*;$_.owner.user_id-ne$i-and$c-gt0-and$c-lt10}|random}while((irm($u+$t.question_id+'/answers'+$s)).items.owner.user_id-contains$i)
$t.link

Explanation:

param($i)
$q=irm (($u="api.stackexchange.com/questions/")+($s="?tagged=code-golf&site=codegolf")) #run this query
do{ #until we find a valid question, get a random one that fits the basic specs
    $t=$q.items|?{$c=$_|% an*;$_.owner.user_id-ne$i-and$c-gt0-and$c-lt10}|random
}while( #Get all of the answers, and their owners into an array, check it doens't contain the provided id
(irm($u+$t.question_id+'/answers'+$s)).items.owner.user_id-contains$i
)
$t.link #output the question link

add 4 bytes for a version which opens it in webbrowser

param($i)$q=irm (($u="api.stackexchange.com/questions/")+($s="?tagged=code-golf&site=codegolf"))
do{$t=$q.items|?{$c=$_|% an*;$_.owner.user_id-ne$i-and$c-gt0-and$c-lt10}|random}while((irm($u+$t.question_id+'/answers'+$s)).items.owner.user_id-contains$i)
saps $t.link
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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