Construire un navigateur XKCD défectueux

75

Défi

Étant donné le numéro d’une bande dessinée XKCD, éditez le titre de cette bande dessinée (le texte survolé).

Cependant, le programme doit jeter une erreur quand on leur donne les chiffres 859ou 404.

Règles

Le numéro donné sera toujours une bande dessinée existante (sauf 404).

Votre programme ne doit pas générer d'erreur pour les autres nombres que 859ou 404.

Pour référence, la bande dessinée 404n'existe pas et 859est:

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

Les raccourcisseurs d'URL sont interdits. Vous pouvez utiliser Internet pour obtenir le texte du titre.

Exemples

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.

Prime

J'attribuerai une prime à la réponse la plus courte qui échouera sur la bande dessinée 859 car elle est mal écrite au lieu de rechercher le numéro.

Votre programme peut se casser sur d’autres textes alternatifs (tels que 744) à condition qu’ils aient des parenthèses, des guillemets, etc. sans égaux.

Gagnant

Le code le plus court en octets gagne.

Beta Decay
la source
2
Puisqu'il y a d'autres bandes dessinées avec des textes alternatifs révolutionnaires (voir 744 ), est-ce que ça va si un programme se casse aussi?
totalement humain
8
@totallyhuman Vous auriez dû ajouter un avertissement légèrement
NSFW
11
Contradiction dans le défi: "ne doit pas renvoyer d'erreur pour aucun autre chiffre que " 859ou 404"et" peut se briser sur d'autres textes alternatifs ".
Aschepler
3
@aschepler Ce dernier est uniquement pour la prime
Beta Decay
4
@Kzqai Bonne question, mais je pense que vous sous-estimez peut-être un peu le trafic impliqué dans un DDOS, mais aussi le trafic que xkcd.com a déjà. Je ne m'attendrais pas à ce que le trafic généré par les réponses ici soit significatif par rapport à l'un ou l'autre.
Trichoplax

Réponses:

107

Python 2.7 + xkcd , 55 octets

xkcd est un package Python tiers. En Python, il y a un paquet pour tout !

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

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

Pour 859: IndexError: list index out of range

M. Xcoder
la source
89
Le paquet a été écrit avant ce défi et n'a pas été écrit spécifiquement pour ce défi, il s'avère simplement très approprié.
Draco18s
4
Wow, Python est devenu plus attrayant!
Nat
6
Par coïncidence, Python supporte bien import'ing antigravity.
Pourtant, un autre utilisateur
39
Python vient-il de Mathematica pour relever ce défi?
Arcturus
22

Python 2 + Requests , 104 102 95 94 octets

-2 octets grâce à Erik l'Outgolfer. -1 octet grâce à Jonathan Allan.

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

Obligatoire:

import antigravity

Script mal écrit, 98 octets

Donc, écrire de mauvais scripts est en réalité difficile à faire intentionnellement ... Cela se répercute également sur d’autres bandes dessinées, car ils contiennent des guillemets, il n’est pas certain que ce soit correct.

from requests import*
exec'print "%s"'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt']
totalement humain
la source
4
Je pense que vous pouvez enlever ,a.
Erik the Outgolfer
1
Vous pouvez passer n in[404,859]à n==859, car le décodeur JSON échoue de 404toute façon.
musicman523
7
... http://peut être utilisé ici aussi, je pense.
Jonathan Allan
1
Comment exécutez-vous cela avec un paramètre? Comment fais-tu un lambda sans nom?
MrZander
1
@MrZander La première ligne est un lambda anonyme pouvant être affecté à une variable à exécuter. Par exemple, les deux f = lambda n: n * 2; print f(2)ou (lambda n: n * 2)(2)imprimeront 4.
totalement humain
18

Python 2 + xkcd, 82 octets

Script mal écrit

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

Ajoute et ajoute ''', qui, sauf si le texte en contient ''', ne se cassera pas, même pour les autres guillemets. C’est-à-dire, sauf si le texte contient ;;, qui est remplacé par '''(élimination re). Ceci ne s'applique que pour 859, et donc ce code se casse 859. : P

En outre, on ne doit jamais le evalcontenu Internet au hasard, parce que si en xkcd.getComic(n).altTextquelque sorte devenu '''+__import__('os').system('rm -rf / --no-preserve-root')+''', il causerait beaucoup de mauvaises choses à se produire. À savoir, cela supprimerait tout ce qui est accessible de manière non-sudo sur l'ordinateur, sauf si vous exécutez des programmes codegolf dans sudo (également déconseillé): P

HyperNeutrino
la source
1
Mal écrit et échoue pour ce cas de test, 859? Quelqu'un va recevoir une prime, je suppose ...
M. Xcoder le
12
Ah la grimace pour évaluer du contenu aléatoire sur Internet - bravo! : P
Luke Briggs le
@ LukeBriggs Cela devrait théoriquement être sûr ... Je veux dire, mon ordinateur n'a pas encore explosé , donc ça devrait aller, n'est-ce pas? : P Mais vous pouvez aussi utiliser __import__('ast').literal_evalà la place de evalsi vous voulez vraiment: P
HyperNeutrino
Est-ce que ça casse sur 744?
Draco18s
@ Draco18s Cela ne devrait pas, car les citations triples ne se soucient pas des citations mal assorties, et il n'y en a pas ;;.
HyperNeutrino
11

Wolfram Language / Mathematica, 118 117 octets

enregistré un octet grâce à numbermanic

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

Explication:

Utilisez StringTemplatepour former l'URL à partir de l'entrée.

Import[..., "RawJSON"]importe l'objet JSON et le analyse dans un fichier Assocation.

Sélectionnez la valeur pour la clé "alt".

Prenez ce résultat et essayez d'interpréter la chaîne en tant que HTML ( Import[#,"HTML"]). Si cela ne change rien, le résultat est répercuté, s'il revient $Failed. Cela attrape 859 parce que

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

résulte en:

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

404 échoue parce que

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

résultats en $Failed.

chuy
la source
Quelle version utilisez-vous? Je reçois The Import element "RawJSON" is not present when importing as JSONle 10.0.1.
Julian Wolf
@totallyhuman Eh bien, il n'est probablement pas nécessaire de rechercher le numéro 859. (Voir la condition de prime dans la question.)
Beta Decay le
@ JulianWolf J'utilise 11.1.0. Je pense que le support "RawJSON" a été ajouté dans 10.2.
Chuy
4
@totallyhuman Il ne fait pas de vérification explicite, mais c'est en quoi ImportString[#,"HTML"]consiste le problème.
chuy
1
@numbermaniac En effet je peux. Je ne peux pas croire que j'ai raté ça, merci!
Chuy
8

Java 8, 255 176 octets

Merci à @ OlivierGrégoire de me faire sentir comme un idiot et 79 octets de moins. ;)

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

Cela semble trop lourd ... Toujours lourd, mais "d'accord" pour Java ...

Explication:

  • i->{...} Lambda qui fonctionne comme String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() tout lire du donné InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()cela crée un InputStreamqui référence le corps de la réponse http://xkcd.com/{comic_id}/info.0.jsonqui est la page d'information de la bande dessinée souhaitée
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Supprime tout sauf le texte alternatif (jusqu'à la première citation double)
  • retour implicite

Autre approche plus courte, 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")

Ce n'est pas ma solution, donc je ne veux pas poster ceci en premier. Tous les crédits appartiennent à @ OlivierGrégoire.

Roman Gräf
la source
1
Vos importations sont manquantes! . En outre, il n'y a presque aucune tentative de golf cette réponse ...
Olivier Grégoire
Ajoutée. Un peu moins de 2 ^ 8. Au moins la taille de mon programme tient dans un octet :)
Roman Gräf
i->new java.util.Scanner(new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()).useDelimiter("\\a").next().replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","")(176 octets, attention aux personnages de cutter des commentaires du SO) Et j'ai à peine joué au golf ici.
Olivier Grégoire
Oh! Je pensais que Scanner#useDelimiterrien ne revenait ... Mieux vaut lire la documentation la prochaine fois;)
Roman Gräf
1
Je viens de remarquer que vous pouvez créer votre propre Functionclasse qui vous permet de lancer Exception. Aujourd'hui n'est pas mon jour.
Roman Gräf
7

PHP, 89 86 85 octets

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

Retourne null pour 404 et 859

Enregistrer sous xkcd.php et exécuter avec le numéro de bande dessinée ...

$ php xkcd.php 386
Jared Mellentine
la source
utiliser $argnau lieu de $argv[1], _au lieu deNULL
Jörg Hülsermann
@ JörgHülsermann Merci! Je ne savais pas à propos de _. $ argn ne semble pas fonctionner cependant.
Jared Mellentine
php.net/manual/en/features.commandline.options.php $argn est disponible si vous exécutez PHP à partir de la ligne de commande avec -Rl' -Foption ou
Jörg Hülsermann
_n'est pas équivalent à NULLen PHP. Ce script génère une erreur indiquant _qu’il s’agit d’une constante non définie.
Andy
@Andy Si un avis n'est pas autorisé, cela ""constitue une meilleure alternative, car NULLJared en donne un exemple pour $argn codegolf.stackexchange.com/questions/114146/…
Jörg Hülsermann le
5

PHP 5.3, 280 268 262 261 180 octets


1. Enregistré 11 grâce à certaines suggestions de Roman Gräf
2. Enregistré 1 octet en utilisant un lien http au lieu de https
3. Enregistré 6 octets supplémentaires grâce à Kevin_Kinsay
4. Enregistré un autre octet avec la suggestion d'Andy
5. Une révision majeure:

  • erreurs supprimées avec @ au lieu de changer libxml_use_internal_errors
  • utilisé à la implode(0,file(""))place de file_get_contents("")(2 octets)
  • déplacé la $xdéfinition à l'intérieur duif
  • Utiliser throw 0au lieu de lancer une exception (cela bloque le programme)
  • avec le @je peux maintenant omettre le comicLinkremplacer.


Mon premier essai sur le golf.

Le DOMDocument se brise lorsqu’il rencontre des liens comicLinks avec un ID de dobule, il a donc fallu que je les supprime. Il y a probablement une meilleure façon de le faire.

Crashes en essayant d'obtenir non. 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
la source
2
Bienvenue chez PPCG! Je pense que vous pouvez supprimer le test si, $x==404parce que l'autre code échouera sur la réponse 404 ... Vous pouvez également remplacer throw new Exceptionpar un dieappel et supprimer les crochets autour throw new Exception("")/ diecar il ne s'agit que d'une seule déclaration
Roman Gräf
1
Merci! Je ne savais pas si die () compterait comme "une erreur";)
Ezenhis
1
Utilisez "1" au lieu de "true" sur libxml_use_internal_errors. Vous pouvez probablement passer 0 à l'exception et enregistrer un équivalent de citation. La fermeture?> Devrait être facultative.
Kevin_Kinsey
Les variables sont interpolées entre guillemets, elles "http://xkcd.com/".$xpeuvent donc devenir des "http://xkcd.com/$x"économies d'un octet :)
Andy
BTW, +1 pour utiliser la technique d'analyse "correcte" (analyseur XML) par opposition à mon horrible hack regex;)
Kevin_Kinsey
5

Python + xkcd , 54 octets

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

Vérification

>>> 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
la source
Je viens juste de remarquer cela. Beau golf!
Beta Decay
5

Le Python a déjà gagné, mais peu importe ...

bash + curl + sed; 88 ~ 91 heh octets

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

Oui pour l'analyse JSON regex!

EDIT NoLongerBreathedIn a remarqué (dans 648 jours dans le futur!) Que cela avait échoué après 2048 en raison d’un imprévu \"dans le code JSON de cette entrée. La regex a été mise à jour ci-dessus; c'était l'habitude sed 's/.*alt": "\([^"]\+\).*/\1/').

Le printfwrapper gère parfaitement le fait que les caractères Unicode sont représentés dans la \unnnnnotation:

$ 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༧༦࿐༄

 

Cela échoue avec les messages 404 et 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$

Le $à la fin de la sortie est mon invite, et le littéralement imprimé \njuste avant qu'il fasse partie de la chaîne printf.

J'ai délibérément utilisé printfparce qu'il analyserait Unicode et tomberait terriblement sur ce poste spécifique.

i336_
la source
Aussi barfs sur 2048. Je pense que ça barfs sur les guillemets doubles?
NoLongerBreathedIn
Belle prise. Poster mis à jour. En regardant le sedmorceau, vous pouvez voir qu’il cherchait alt": "puis lisait jusqu’à ce qu’il en trouve un ". Woops, apparemment ... (Je me demande combien de ces solutions échoueraient à un test unitaire de ev̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀ ?: P)
i336_
4

Python 2 , 115 à 106 octets

-8 octets grâce aux ovs. -1 octet grâce à Jonathan Allan.

Je pensais juste que je mettrais une réponse de bibliothèque standard là-bas.

lambda n:[json.load(urllib.urlopen('http://xkcd.com/%d/info.0.json'%n))['alt']][n==859]
import urllib,json
totalement humain
la source
1
lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859]pour -8 octets.
ovs
1
Devrait travailler avec http://trop sauver un octet.
Jonathan Allan
4

Bash + curl + jq: 73 66 octets

La réponse la plus courte qui n'utilise pas une bibliothèque spécifique à xkcd. jq est un outil de manipulation d'objets json dans le shell, et il est livré avec un langage d'analyse pour le faire.

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 ci-dessous:

curl -Ls - Requête, mais n'hésitez pas à rediriger (dans ce cas, vers le site https) et à ne pas générer de sortie non liée.

xkcd.com/$1/info.0.json - Volé sans vergogne d'une autre réponse.

|jq -r- Exécuter jqen mode "sortie brute" sur la commande suivante.

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

Maintenant, le script a été retravaillé pour utiliser //l'équivalent de a or bpython, et nous utilisons un |notpour faire en sorte que toute valeur vraie soit considérée comme fausse, de sorte que la seconde //puisse imprimer.alt

Aviator45003
la source
2

JavaScript (ES6), 177 175 octets

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

Collez-le dans la console de votre navigateur, puis exécutez f(859)ou f(404)etc. - ces deux-là devraient se tromper dans la console, même s'ils ne sont pas codés en dur, les autres s'affichent.

Première publication depuis un moment, désolée si elle ne respecte pas les règles ...!

James Thorpe
la source
Utilisez x=>au lieu de (x)=>.
user75200
2

PHP, 160 octets

<? 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
la source
Attends ... ce n'est pas à la spécification. Fixing ...
Kevin_Kinsey
Fixé. J'ai dû ajouter environ 50 octets cependant ... :(
Kevin_Kinsey
1
vous pouvez supprimer 7 caractères, supprimer l'écho et déplacer l'attribution $ c à l'intérieur du substrat
Einacio
1
@BetaDecay parce que ne pas vérifier le numéro d'entrée donne des points supplémentaires
Einacio
1
@BetaDecay, un script qui dépend du contenu semble mal écrit pour moi. Tout autre titre commençant comme ça le briserait. Kevin_Kinsey vous pouvez remplacer ENT_QUOTES par sa valeur = 3
Einacio
1

Perl, 129 167 octets

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

EDIT: Psyché c'est en fait

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>/)}

Importez le décodage HTML et l'accès HTTP, puis imprimez le groupe correspondant au (...) dans

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

(économiser un peu en omettant {{Title de la requête)

Pour 404 et 859, la mort.

archéphyrryx
la source
Que voulez-vous dire par "gère correctement le 859"?
Beta Decay
@BetaDecay Il imprime le texte
alternatif réel
1
the program must throw an error when given the numbers 859 or 404
Beta Decay
En quoi consiste "jeter une erreur"?
archaephyrryx
Nvm dieest assez court
archaephyrryx
1

BASH, 111 108 octets

a = $ (cat) curl -s https://xkcd.com/ $ a / | grep -oP '(? <= texte du titre:) ([^}}] *)' [$ a = 404] && echo "$ a introuvable"

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


Pour exécuter:
remplacez # par le nombre de bandes dessinées. Exécuter en ligne de commande.

Merci @Ale pour la suggestion!

Silentziler
la source
Pourquoi lire à partir de l'entrée standard en utilisant cat au lieu d'utiliser simplement $ 1 à partir de la ligne de commande? Cela permettrait d'économiser quelques octets ...
Ale
1

Javascript (ES6), 118 96 94 octets

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

Vous pouvez le coller dans la console de votre navigateur et le lancer f(123). Mais faites-le sur une page qui se trouve déjà sur xkcd.com ou vous verrez une erreur CORS.

Pour 404, cela échoue avec:

Uncaught (promis) SyntaxError: Jeton inattendu <dans JSON en position 0

Pour 859, il échoue avec:

Uncaught (promis) SyntaxError: manquant) après la liste d'arguments

Mise à jour: la dernière version vérifie correctement le texte de remplacement au lieu de rechercher uniquement 859 et supprime 2 autres octets.

Christiaan Westerbeek
la source
Malheureusement, cela échoue sur tout titletext contenant une apostrophe (par exemple, 1084).
ETHproductions