Give me some questions to answer!

15

0

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.

Beta Decay

Posted 2017-05-24T06:26:37.777

Reputation: 21 478

Answers

4

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

colsw

Posted 2017-05-24T06:26:37.777

Reputation: 3 195

5

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)))()

Shaggy

Posted 2017-05-24T06:26:37.777

Reputation: 24 623

1based my powershell answer on this one, nice reuse of the strings for the api. – colsw – 2017-05-24T10:47:39.523

At which point do you get banned permanently? ;) – Beta Decay – 2017-05-24T11:13:44.703

@BetaDecay, if the API challenges pick up pace again, I might soon find out! :D – Shaggy – 2017-05-24T11:14:55.513

You can use the api tokens from here: https://stackapps.com/q/7384/45852 to increase your rate limit.

– programmer5000 – 2017-05-24T13:57:27.033

Gave me "Golf you an Anagram for great good!" (my own question) for the default id! :D – Arjun – 2017-05-24T14:59:05.700

You put the heart across me there, @Arjun; thought you were about to tell me it returned one of your own questions for your ID! – Shaggy – 2017-05-24T15:00:42.153

Don't worry, that's not the case! :) – Arjun – 2017-05-24T15:02:20.523

This is only returning questions which are on the front page... :P Not exactly what I was looking for – Beta Decay – 2017-05-24T18:52:32.677

@BetaDecay, will it suffice as a solution to the challenge? If not, I could (in ascending order of extra bytes): 1. Get the first 5 pages of questions, 2. get the last page, 3. both of the above, 4. Get all questions. Let me know which would meet the requirements but note that the last option involves a lot of queries to the API. – Shaggy – 2017-05-24T19:25:03.930

@Shaggy Well I think it is within rules, so you don't need to change it, but it doesn't really fit into the digging questions from PPCG's past box :/ – Beta Decay – 2017-05-24T19:27:01.010

1@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. – Shaggy – 2017-05-24T19:31:35.223

@BetaDecay; boomarklet now available :) – Shaggy – 2017-05-25T09:35:24.610

Nice! This'll be great :D – Beta Decay – 2017-05-25T09:37:06.587