Build a Faulty XKCD Browser

75

11

Challenge

Given the number of an XKCD comic, output the title text of that comic (the mouseover text).

However, the program must throw an error when given the numbers 859 or 404.

Rules

The number given will always be an existing comic (except 404).

Your program must not throw an error for any other numbers than 859 or 404.

For reference, comic 404 does not exist and 859 is:

Brains aside, I wonder how many poorly-written xkcd.com-parsing scripts will break on this title (or ;;"''{<<[' this mouseover text."

Url shorteners are disallowed. You may use the internet to get the title text.

Examples

Input > Output
1642 > "That last LinkedIn request set a new record for the most energetic physical event ever observed. Maybe we should respond." "Nah."
1385 > ::PLOOOOSH:: Looks like you won't be making it to Vinland today, Leaf Erikson.
1275 > If replacing all the '3's doesn't fix your code, remove the 4s, too, with 'ceiling(pi) / floor(pi) * pi * r^floor(pi)'. Mmm, floor pie.
1706 > Plus, now I know that I have risk factors for elbow dysplasia, heartworm, parvo, and mange.

Bounty

I will award a bounty to the shortest answer which fails on comic 859 because it's poorly written instead of checking for the number.

Your program may break on other alt texts (such as 744) providing they have unmatched parentheses, quotation marks etc.

Winning

Shortest code in bytes wins.

Beta Decay

Posted 2017-06-30T13:24:23.147

Reputation: 21 478

Is returning null valid as Error? – Roman Gräf – 2017-06-30T16:23:57.480

@RomanGräf Uhh yeah, I think it can be – Beta Decay – 2017-06-30T16:25:07.257

Do we need to parse html entities like '? – thegreatemu – 2017-06-30T16:26:05.840

@thegreatemu Yes – Beta Decay – 2017-06-30T16:28:09.300

2

Since there are other comics with script-breaking alt texts (see 744), is it okay if a program breaks on those too?

– totallyhuman – 2017-06-30T17:16:21.420

8@totallyhuman You should've added a slightly-NSFW-warning to that :P – HyperNeutrino – 2017-06-30T17:27:44.640

1@totallyhuman Yes, that's fine – Beta Decay – 2017-06-30T17:57:35.003

11Contradiction in the challenge: "must not throw an error for any other numbers than 859 or 404" and "may break on other alt texts". – aschepler – 2017-06-30T19:44:23.260

3@aschepler The latter is only for the bounty – Beta Decay – 2017-06-30T20:58:31.387

1@BetaDecay this suggests the bounty may be applied to an answer that is invalid, inviting invalid answers. – trichoplax – 2017-07-02T08:14:06.497

1Or should the invalid code be included as an aside in a valid answer? – trichoplax – 2017-07-02T08:14:58.573

Isn't this likely to be akin unto a DDOS against the site? And thus should be done with permission? – Kzqai – 2017-07-05T00:08:56.590

4@Kzqai Good question, but I think you may be slightly underestimating how much traffic is involved in a DDOS, and also how much traffic xkcd.com already has. I wouldn't expect the traffic generated from answers here to be significant compared to either of those. – trichoplax – 2017-07-12T01:26:16.103

Answers

107

Python 2.7 + xkcd, 55 bytes

xkcd is a third-party Python package. In Python, there is a package for everything!

lambda n:[xkcd.getComic(n).altText][n==859]
import xkcd

For 404: urllib2.HTTPError: HTTP Error 404: Not Found

For 859: IndexError: list index out of range

Mr. Xcoder

Posted 2017-06-30T13:24:23.147

Reputation: 39 774

90The package was written before this challenge and wasn't written specifically for this challenge, it just ends up being *highly* appropriate. – Draco18s no longer trusts SE – 2017-06-30T16:49:13.983

4Wow, Python just got more attractive! – Nat – 2017-06-30T22:56:20.687

14

@Nat Come join Us!

– jkd – 2017-07-01T02:16:58.007

1

The pypi page says it's Python 2 compatible also, fwiw. Great find!

– BigBlueHat – 2017-07-01T14:03:23.453

6Coincidentally, python does indeed support import'ing antigravity. – Yet Another User – 2017-07-01T17:43:58.980

40Did Python just Mathematica this challenge? – Arcturus – 2017-07-02T02:21:12.970

22

Python 2 + Requests, 104 102 95 94 bytes

-2 bytes thanks to Erik the Outgolfer. -1 byte thanks to Jonathan Allan.

lambda n:[get('http://xkcd.com/%d/info.0.json'%n).json()['alt']][n==859]
from requests import*

Obligatory:

import antigravity

Poorly written script, 98 bytes

So, writing poor scripts is actually hard to do intentionally... This also breaks on other comics because they contain quotes, not sure if that's okay.

from requests import*
exec'print "%s"'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt']

totallyhuman

Posted 2017-06-30T13:24:23.147

Reputation: 15 378

4I think you can remove ,a. – Erik the Outgolfer – 2017-06-30T13:54:14.897

Oh, I didn't think of that. Thanks! – totallyhuman – 2017-06-30T13:55:30.030

1You can change n in[404,859] to n==859, because the JSON decoder fails for 404 anyway. – musicman523 – 2017-06-30T14:11:36.743

@musicman523 Ninja'd you. ;) – totallyhuman – 2017-06-30T14:12:07.050

@totallyhuman Ya got me ;) – musicman523 – 2017-06-30T14:13:54.017

7... http:// can be used here too, I think. – Jonathan Allan – 2017-06-30T14:53:17.727

1how do you actually run this with a parameter? Like, how do you run a nameless lambda? – MrZander – 2017-06-30T16:32:26.927

1@MrZander The first line is an anonymous lambda that can be assigned to a variable to be run. For example, both f = lambda n: n * 2; print f(2) or (lambda n: n * 2)(2) will print 4. – totallyhuman – 2017-06-30T16:34:14.423

@totallyhuman Is it standard on codegolf.se that user input doesn't need to be counted towards total character count? – MrZander – 2017-06-30T16:36:35.967

@MrZander Yes, it is standard, and unused function names do not add towards the score. – Mr. Xcoder – 2017-06-30T16:38:22.083

If you're willing to add 4 extra bytes, you can stop it from breaking on any comic with quotes: from requests import*;exec'print """%s"""'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt'] – TheInitializer – 2017-07-02T23:12:56.243

18

Python 2 + xkcd, 82 bytes

Poorly written script

lambda n:eval("'''%s'''"%xkcd.getComic(n).altText.replace(';;',"'''"))
import xkcd

Appends and prepends ''', which, unless the text contains ''', will not break, even for other quotation marks. That is, except if the text contains ;;, which gets replaced with ''' (eliminating re). This only applies for 859, and thus this code breaks on 859. :P

Also, one should never eval random internet content, because if xkcd.getComic(n).altText somehow became '''+__import__('os').system('rm -rf / --no-preserve-root')+''', it would cause many bad things to happen. Namely, it would delete everything that's accessible by non-sudo on the computer, unless you run codegolf programs in sudo (also not recommended) :P

HyperNeutrino

Posted 2017-06-30T13:24:23.147

Reputation: 26 575

1Poorly written and fails for that test case, 859? Someone is going to get a bounty, I suppose... – Mr. Xcoder – 2017-06-30T17:55:19.037

12Ah the cringe for evaling random content from the internet - bravo! :P – Luke Briggs – 2017-07-03T00:17:18.773

@LukeBriggs It should theoretically be safe... I mean, my computer hasn't exploded (yet) so it should be fine, right? :P But alternatively you could use __import__('ast').literal_eval in place of eval if you really wanted :P – HyperNeutrino – 2017-07-05T02:30:16.103

Does it break on 744? – Draco18s no longer trusts SE – 2017-07-05T19:17:28.587

@Draco18s It shouldn't, because the triple quotes don't care about the mismatched quotes, and there's no ;;. – HyperNeutrino – 2017-07-05T19:54:27.977

Noted. :) Was just curious. – Draco18s no longer trusts SE – 2017-07-05T20:04:21.163

11

Wolfram Language/Mathematica, 118 117 bytes

saved a byte thanks to numbermanic

If[ImportString[#,"HTML"]===#,#,$Failed]&@Import[StringTemplate["http://xkcd.com/``/info.0.json"]@#,"RawJSON"]@"alt"&

Explanation:

Use StringTemplateto form the URL from the input.

Import[..., "RawJSON"] imports the JSON object and parses it into an Assocation.

Select the value for the key "alt".

Take this result and try to interpret the string as HTML (Import[#,"HTML"]). If this doesn't change anything pass the result through, if it does return $Failed. This catches 859 because

ImportString[
 "Brains aside, I wonder how many poorly-written xkcd.com-parsing 
  scripts will break on this title (or ;;\"''{<<[' this mouseover text.\"","HTML"]

results in:

Brains aside, I wonder how many poorly-written xkcd.com-parsing 
scripts will break on this title (or ;;"''{

404 fails because

If[
 ImportString[$Failed["alt"], "HTML"] === $Failed["alt"], 
 $Failed["alt"],
 $Failed]

results in $Failed.

chuy

Posted 2017-06-30T13:24:23.147

Reputation: 389

What version are you using? I get The Import element "RawJSON" is not present when importing as JSON on 10.0.1. – Julian Wolf – 2017-06-30T16:46:48.293

@totallyhuman Well it probably doesn't need to check for 859. (See the bounty condition in the question) – Beta Decay – 2017-06-30T16:49:02.147

@JulianWolf I am using 11.1.0. I think "RawJSON" support was added in 10.2. – chuy – 2017-06-30T16:58:44.040

4@totallyhuman It doesn't do an explicit check, but that's what the ImportString[#,"HTML"] bit is all about. – chuy – 2017-06-30T17:02:51.783

Could you save a byte by using @"alt" at the end? – numbermaniac – 2017-07-04T07:57:08.033

1@numbermaniac Indeed I can. Can't believe I missed that, thanks! – chuy – 2017-07-06T13:16:09.447

8

Java 8, 255 176 bytes

Thanks to @OlivierGrégoire for making me feel like an idiot and 79 bytes off. ;)

i->new java.util.Scanner(new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()).useDelimiter("\\a").next().replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","")

This feels way too heavy... Still heavy, but "okay" for java...

Explanation:

  • i->{...} Lambda that works like String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() read everything from the given InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream() this creates an InputStream which references the response body of http://xkcd.com/{comic_id}/info.0.json which is the info page of the desired comic
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Removes everything except for the alt text (till the first double quote)
  • implicit return

Alternate shorter approach, Java + json.org, 150

i->i==859?new Long(""):new org.json.JSONObject(new org.json.JSONTokener(new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream())).get("alt")

This is not my solution so I don't want to post this as the first. All the credits belong to @OlivierGrégoire.

Roman Gräf

Posted 2017-06-30T13:24:23.147

Reputation: 2 915

1Your imports are missing!. Also, there's nearly zero attempt to golf this answer... – Olivier Grégoire – 2017-06-30T18:39:28.230

Added. Just under 2^8. At least the size of my programm fits in one byte :) – Roman Gräf – 2017-06-30T18:44:33.927

i->new java.util.Scanner(new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()).useDelimiter("\\a").next().replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") (176 bytes, careful to the SO's comment cutter characters) And I just barely golfed anything here. – Olivier Grégoire – 2017-06-30T18:49:50.080

Oh! I thought Scanner#useDelimiter returns void... Better read the docs next time ;) – Roman Gräf – 2017-06-30T18:52:11.317

1I just noticed you can create your own Function class that allows you to throw Exception.. Today's​ not my day. – Roman Gräf – 2017-06-30T18:54:33.447

If you use the basic, official JSON library (need to change the title to "Java + JSON.org"), you can get it down to 131 bytes: i->new org.json.JSONObject(new org.json.JSONTokener(new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream())).get("alt") – Olivier Grégoire – 2017-06-30T19:11:55.053

I think that one doesn't fail on #859.. But wait! There is a java json default library? I always used gson... – Roman Gräf – 2017-06-30T19:14:58.580

It is not required to fail on 859! It says that we may not throw errors on numbers other than 404 and 859! Meaning, we may but aren't forced to throw errors on those numbers. – Olivier Grégoire – 2017-06-30T19:41:50.840

"However, the program must throw an error when given the numbers 859 or 404." ~Second paragraph of ##Challenge – Roman Gräf – 2017-06-30T19:45:04.607

Then be creative! i->i==859?new Long(""):new org.json.JSONObject(new org.json.JSONTokener(new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream())).get("alt") for 150 bytes. – Olivier Grégoire – 2017-06-30T20:27:51.627

I think that is your own solution and not mine anymore. if you still want me to include it I'll do that :) – Roman Gräf – 2017-06-30T20:29:37.387

It's your call: I won't post it as mine. My goal on this website is to make my brain work, not to gain rep. – Olivier Grégoire – 2017-06-30T20:30:52.113

But still you've done very well... I should also get my brain working (or go to bed, I've slept too few yesterday) – Roman Gräf – 2017-06-30T20:34:41.213

By the way, there is no official Java Json library (there's a Java EE spec, and Jackson is its reference implementation). The library I mentioned is the library done by the guys who made the Json spec (so it's "official" by Json.org, not by Java). You're free to use whatever library you want. I personally use Gson as well, but the byte-count is unreasonable for golfing. – Olivier Grégoire – 2017-07-01T18:07:38.523

7

PHP, 89 86 85 bytes

<?=($a=$argv[1])==859?_:@json_decode(file("http://xkcd.com/$a/info.0.json")[0])->alt;

Returns null for 404 and 859

Save as xkcd.php and run with the comic number...

$ php xkcd.php 386

Jared Mellentine

Posted 2017-06-30T13:24:23.147

Reputation: 101

use $argninstead of $argv[1] , _ instead of NULL – Jörg Hülsermann – 2017-06-30T22:52:33.920

@JörgHülsermann Thanks! I didn't know about _. $argn doesn't seem to work though. – Jared Mellentine – 2017-06-30T23:19:38.947

http://php.net/manual/en/features.commandline.options.php $argn is available if you run PHP from the command Line with the -R or the -F option – Jörg Hülsermann – 2017-06-30T23:25:43.803

_ is not equivalent to NULL in PHP. This script throws an error about _ being an undefined constant. – Andy – 2017-06-30T23:45:54.783

@Andy If a Notice is not allowed "" is a better alternative as NULL Jared here is an example for $argn https://codegolf.stackexchange.com/questions/114146/get-your-dubs-together/114161#114161

– Jörg Hülsermann – 2017-06-30T23:55:28.560

@JörgHülsermann ah, I didn't realise you meant use it as an arbitrary character to throw a notice :) – Andy – 2017-07-01T08:08:20.987

Didn't know he was serving JSON ... nice work! – Kevin_Kinsey – 2017-07-01T12:15:16.957

Per the other PHP answer, you can save one byte by replacing "https" with "http". – Gras Double – 2017-07-02T19:31:34.387

5

PHP 5.3, 280 268 262 261 180 bytes


1. Saved 11 thanks to some of Roman Gräf's suggestions
2. Saved 1 byte by using http link instead of https
3. Saved another 6 bytes thanks to Kevin_Kinsay
4. Saved another 1 byte with Andy's suggestion
5. A major revision:

  • suppressed errors with @ instead of changing libxml_use_internal_errors
  • used implode(0,file("")) instead of file_get_contents("") (2 bytes)
  • moved the $x definition inside the if
  • Using throw 0 instead of actually throwing an exception (it crashes the program)
  • with the @ I now can omit the comicLink replace.


My first try on golfing.

The DOMDocument breaks when encounters dobule ID comicLinks so I had to remove these. There's probably a nicer way of doing that.

Crashes when trying to get no. 859 ;)

<?php if(($x=$argv[1])==859)throw 0;$a=new DOMDocument;$b=@$a->loadHTML(implode(0,file("http://xkcd.com/$x")));echo $a->getElementsByTagName('img')->item(1)->getAttribute('title');

Ezenhis

Posted 2017-06-30T13:24:23.147

Reputation: 191

2Welcome to PPCG! I think you can remove the test whether $x==404 because the other code will fail on the 404 response... Also you can replace throw new Exception by a die call and remove the brackets around throw new Exception("")/die because it is only a single statement – Roman Gräf – 2017-06-30T15:50:05.140

1Thanks! I wasn't sure if die() would count as "throw an error" ;) – Ezenhis – 2017-06-30T16:28:04.067

1Use "1" instead of 'true' on libxml_use_internal_errors. You can probably pass 0 to the Exception and save one quote equivalent. Closing ?> should be optional. – Kevin_Kinsey – 2017-06-30T16:55:00.310

Variables are interpolated inside double quotes, so "http://xkcd.com/".$x can become "http://xkcd.com/$x" saving one byte :) – Andy – 2017-06-30T23:28:06.710

BTW, +1 for using "proper" parsing technique (XML parser) as opposed to my ugly regex hack ;) – Kevin_Kinsey – 2017-07-01T12:17:10.960

..Just managed to cut 81 bytes :D – Ezenhis – 2017-07-04T14:04:59.243

5

The Python one has already won, but regardless...

bash + curl + sed; 88 ~91 heh bytes

printf "$(curl -s https://xkcd.com/2048/info.0.json|sed 's/.*"alt": "//;s/", "img":.*//')\n"

Yay for regex JSON parsing!

EDIT NoLongerBreathedIn noticed (648 days into the future!) that this failed on post 2048 because of an unexpected \" in that entry's JSON. The regex has been updated above; it used to be sed 's/.*alt": "\([^"]\+\).*/\1/').

The printf wrapper neatly handles the fact that Unicode characters are represented in \unnnn notation:

$ printf "$(curl -s https://xkcd.com/1538/info.0.json | sed 's/.*"alt": "//;s/", "img":.*//')\n"
To me, trying to understand song lyrics feels like when I see text in a dream but it hอᵣd t₀ ᵣeₐd aกd  canٖt fཱྀcu༧༦࿐༄

 

This fails with posts 404 and 859:

404

$ printf "$(curl -s https://xkcd.com/404/info.0.json | sed 's/.*alt": "\([^"]\+\).*/\1/')\n"
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

859

$ printf "$(curl -s https://xkcd.com/859/info.0.json | sed 's/.*alt": "\([^"]\+\).*/\1/')\n"
Brains aside, I wonder how many poorly-written xkcd.com-parsing scripts will break on this title (or ;;\n$

The $ at the end of the output is my prompt, and the literally-printed \n immediately before it is part of the printf string.

I deliberately used printf because it would parse Unicode and fall over terribly on this specific post.

i336_

Posted 2017-06-30T13:24:23.147

Reputation: 151

Also barfs on 2048. I think it barfs on double quotes? – NoLongerBreathedIn – 2019-04-09T18:33:28.540

Nice catch. Post updated. Looking at the sed bit, you can see it was looking for alt": " then reading until it found a ". Woops, apparently... (I wonder how many of these solutions would fail a unit test of e̲͕̲̪v̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ ̴͎͉̳̮a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀? :P) – i336_ – 2019-04-10T01:58:35.243

5

Python + xkcd, 54 bytes

import xkcd
lambda n:xkcd.getComic(*{n}-{859}).altText

Verification

>>> import sys
>>> sys.tracebacklimit = 0
>>>
>>> import xkcd
>>> f = lambda n:xkcd.getComic(*{n}-{859}).altText
>>>
>>> print f(149)
Proper User Policy apparently means Simon Says.
>>>
>>> f(404)
urllib2.HTTPError: HTTP Error 404: Not Found
>>>
>>> f(859)
TypeError: getComic() takes at least 1 argument (0 given)

Dennis

Posted 2017-06-30T13:24:23.147

Reputation: 196 637

I've only just noticed this. Nice golf! – Beta Decay – 2018-07-24T10:18:47.140

4

Python 2, 115 106 bytes

-8 bytes thanks to ovs. -1 byte thanks to Jonathan Allan.

Just thought I'd put a standard library answer out there.

lambda n:[json.load(urllib.urlopen('http://xkcd.com/%d/info.0.json'%n))['alt']][n==859]
import urllib,json

totallyhuman

Posted 2017-06-30T13:24:23.147

Reputation: 15 378

1lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859] for -8 bytes. – ovs – 2017-06-30T14:49:44.840

1Should work with http:// too saving a byte. – Jonathan Allan – 2017-06-30T14:52:07.827

4

Bash + curl + jq: 73 66 bytes

Shortest answer that doesn't use an xkcd-specific library. jq is a tool for manipulating json objects in the shell, and it comes complete with a parsing language to do that.

curl -Ls xkcd.com/$1/info.0.json|jq -r 'if.num==859then.num.a else.alt end'

curl -Ls xkcd.com/$1/info.0.json|jq -r '(.num!=859//.[9]|not)//.alt'

Expansion below:

curl -Ls - Query, but feel free to redirect (in this case to the https site) and give no unrelated output.

xkcd.com/$1/info.0.json - Shamelessly stolen from another answer.

|jq -r - Run jq in "raw output" mode on the following command.

if .num == 859 then .num.a # This fails because you can't get the key 'a' from a property that's an integer else .alt # And this pulls out the 'alt' key from our object. end

Now the script has been re-worked to use // which is the equivalent of a or b in python, and we use a |not to make any true value be considered false, so the second // can print .alt

Aviator45003

Posted 2017-06-30T13:24:23.147

Reputation: 141

2

PHP, 160 bytes

<? preg_match_all('/(tle=\")(.+)(\")\sa/',join(0,file('http://xkcd.com/'.$argv[1])),$a);echo(strstr($c=$a[2][0],'Brains asid'))?$b:html_entity_decode($c,3);

Kevin_Kinsey

Posted 2017-06-30T13:24:23.147

Reputation: 121

Hang on ... this isn't to spec. Fixing ... – Kevin_Kinsey – 2017-06-30T17:00:34.203

Fixed. Had to add about 50 bytes though ... :( – Kevin_Kinsey – 2017-06-30T17:15:40.057

And a few more to handle the ' :( :( – Kevin_Kinsey – 2017-06-30T17:23:50.120

Shaved 1 byte with "implode/file"... – Kevin_Kinsey – 2017-06-30T17:26:37.993

Shaved 10 bytes on the regexp and by using join (alias to implode()), etc. – Kevin_Kinsey – 2017-06-30T17:33:59.483

Nice job. You could probably reduce "Brains aside" to "Brains a" – John Hathwood – 2017-06-30T18:09:29.130

1you can remove 7 chars removing the echo and moving the $c assign inside the substr – Einacio – 2017-06-30T18:11:21.373

Why check the substring instead of check the input? – Beta Decay – 2017-06-30T18:34:17.650

1@BetaDecay because not checking for the input number gives extra points – Einacio – 2017-06-30T18:43:06.307

That's not what I meant. Your program should be poorly written: whether it be the unmatched parentheses, the semicolons or the unmatched quotation marks which break the program – Beta Decay – 2017-06-30T18:45:03.373

1@BetaDecay well, a script that depends on content looks poorly written to me. Any other title starting like that would break it.

Kevin_Kinsey you can replace ENT_QUOTES by its value=3 – Einacio – 2017-06-30T19:54:35.683

Thanks Einacio ... I was looking for that but couldn't figure it from the manual. – Kevin_Kinsey – 2017-06-30T21:49:17.750

Ooh, I need to update it though ... the last version I wc'ed used something besides 'Brains aside' ... hopefully I can get back on this after work and the theatre tonight.... – Kevin_Kinsey – 2017-06-30T21:51:14.237

2

JavaScript (ES6), 177 175 bytes

p=(x)=>{eval(`console.log("${x.alt}")`)};f=(y)=>{var d=document,e=d.createElement("script");e.src=`//dynamic.xkcd.com/api-0/jsonp/comic/${y}?callback=p`;d.body.appendChild(e)}}

Paste this into your browser console, then execute f(859) or f(404) etc - those two should error in the console, despite not being hard coded, the others display.

First post in a while, sorry if it doesn't quite meet the rules...!

James Thorpe

Posted 2017-06-30T13:24:23.147

Reputation: 161

Use x=> instead of (x)=>. – user75200 – 2018-01-13T18:11:43.063

1

Perl, 129 167 bytes

use LWP::Simple;use HTML::Entities;print decode_entities($1)if(get("http://www.xkcd.com/$ARGV[0]")=~m/text: ([^<]*)\}\}<\/div>/)

EDIT: Psyche it's actually

use LWP::Simple;use HTML::Entities;$x=$ARGV[0];if($x==404||$x==859){die}else{print decode_entities($1)if(get("http://www.xkcd.com/$x")=~m/text: ([^<]*)\}\}<\/div>/)}

Import HTML decoding and HTTP accessing, then print the group matching the (...) in

{{Title text: (...)}}</div>

(saving a bit by omitting {{Title from the query)

For 404 and 859, death.

archaephyrryx

Posted 2017-06-30T13:24:23.147

Reputation: 1 035

What do you mean by "properly handles 859"? – Beta Decay – 2017-06-30T18:35:46.240

@BetaDecay It prints the actual alt-text – archaephyrryx – 2017-06-30T18:36:14.330

1*the program must throw an error when given the numbers 859 or 404* – Beta Decay – 2017-06-30T18:37:26.363

What is "throw an error" defined as? – archaephyrryx – 2017-06-30T19:57:47.950

Nvm die is short enough – archaephyrryx – 2017-06-30T20:00:40.427

s/print/say/g also you can use -MModule – DarkHeart – 2017-07-02T05:06:59.617

1

BASH, 111 108 bytes

a=$(cat) curl -s https://xkcd.com/$a/ |grep -oP '(?<=Title text:)([^}}]*)' [ $a = 404 ] && echo "$a not found"

a=#;curl -s https://xkcd.com/$a/ |grep -oP '(?<=Title text:)([^}}]*)';[ $a = 404 ] && echo "$a not found"


To Run:
change # to number of comic. Run from command line.

Thanks @Ale for the suggestion!

Silentziler

Posted 2017-06-30T13:24:23.147

Reputation: 39

Why reading from standard input using cat instead of just using $1 from the command line? It would save some bytes... – Ale – 2017-07-02T00:04:52.197

1

Javascript (ES6), 118 96 94 bytes

f=n=>fetch(`//xkcd.com/${n}/info.0.json`).then(x=>x.json()).then(y=>eval(`alert('${y.alt}')`))

You can paste that in your browser console and run f(123). But do so on a page that is already on xkcd.com or else you'll see a CORS error.

For 404, it fails with:

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

For 859, it fails with:

Uncaught (in promise) SyntaxError: missing ) after argument list

Update: the lastest version properly checks the alt text instead of checking for just 859 and shaves of another 2 bytes.

Christiaan Westerbeek

Posted 2017-06-30T13:24:23.147

Reputation: 863

Sadly, this fails on any titletext containing an apostrophe (e.g. 1084). – ETHproductions – 2017-07-03T22:07:16.683