Costruisci un browser XKCD difettoso


75

Sfida

Dato il numero di un fumetto XKCD, genera il testo del titolo di quel fumetto (il testo del passaggio del mouse).

Tuttavia, il programma deve generare un errore quando vengono indicati i numeri 859o 404.

Regole

Il numero indicato sarà sempre un fumetto esistente (tranne 404).

Il tuo programma non deve generare errori per numeri diversi da 859o 404.

Per riferimento, il fumetto 404non esiste ed 859è:

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

Gli accorciatori di URL non sono consentiti. È possibile utilizzare Internet per ottenere il testo del titolo.

Esempi

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.

generosità

Assegnerò un premio alla risposta più breve che non riesce sul fumetto 859 perché è scritto male invece di controllare il numero.

Il tuo programma potrebbe interrompersi su altri testi alternativi (come 744) a condizione che abbiano parentesi, virgolette ecc.

vincente

Vince il codice più breve in byte.


2
Dal momento che ci sono altri fumetti con testi alt che spezzano gli script (vedi 744 ), va bene anche se un programma si rompe anche su quelli?
totalmente umano il

8
@totallyhuman Avresti dovuto aggiungere un avvertimento leggermente NSFW a questo: P
HyperNeutrino,

11
Contraddizione nella sfida: "non deve generare un errore per numeri diversi da 859o 404" e "può rompersi su altri testi alternativi".
aschepler,

3
@aschepler Quest'ultimo è solo per la generosità
Decadimento beta

4
@Kzqai Bella domanda, ma penso che potresti sottovalutare leggermente la quantità di traffico coinvolta in un DDOS e anche la quantità di traffico che xkcd.com ha già. Non mi aspetto che il traffico generato dalle risposte qui sia significativo rispetto a nessuno dei due.
trichoplax,

Risposte:


107

Python 2.7 + xkcd , 55 byte

xkcd è un pacchetto Python di terze parti. In Python, c'è un pacchetto per tutto !

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

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

Per 859: IndexError: list index out of range


89
Il pacchetto è stato scritto prima di questa sfida e non è stato scritto appositamente per questa sfida, ma finisce per essere altamente appropriato.
Draco18s

4
Caspita, Python è appena diventato più attraente!
Nat


6
Per coincidenza, Python supporta davvero import'ing antigravity.
Ancora un altro utente il

39
Python ha appena maturato questa sfida?
Arcturus,

22

Richieste Python 2 + , 104 102 95 94 byte

-2 byte grazie a Erik the Outgolfer. -1 byte grazie a Jonathan Allan.

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

Obbligatorio:

import antigravity

Script scritto male, 98 byte

Quindi, scrivere script scadenti è in realtà difficile da fare intenzionalmente ... Ciò si interrompe anche su altri fumetti perché contengono citazioni, non sono sicuro che vada bene.

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

4
Penso che tu possa rimuovere ,a.
Erik the Outgolfer,

1
È possibile passare n in[404,859]a n==859, perché il decoder JSON non riesce 404comunque.
musicman523

7
... http://può essere usato anche qui, credo.
Jonathan Allan,

1
come si esegue effettivamente questo con un parametro? Come, come gestisci una lambda senza nome?
MrZander,

1
@MrZander La prima riga è un lambda anonimo che può essere assegnato a una variabile da eseguire. Ad esempio, entrambi f = lambda n: n * 2; print f(2)o (lambda n: n * 2)(2)stamperanno 4.
totalmente umano il

18

Python 2 + xkcd, 82 byte

Sceneggiatura scritta male

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

Aggiunge e antepone ''', che, a meno che il testo non contenga ''', non si spezzerà, nemmeno per altre virgolette. Cioè, tranne se il testo contiene ;;, che viene sostituito da '''(eliminando re). Questo vale solo per 859, e quindi questo codice si interrompe 859. : P

Inoltre, non si dovrebbe mai evalcasuali contenuti Internet, perché se in xkcd.getComic(n).altTextqualche modo diventasse '''+__import__('os').system('rm -rf / --no-preserve-root')+''', ciò causerebbe molte cose brutte. Vale a dire, eliminerebbe tutto ciò che è accessibile da non-sudo sul computer, a meno che non si eseguano programmi codegolf in sudo (anche non consigliato): P


1
Scritto male e non riesce per questo banco di prova, 859? Qualcuno otterrà una taglia, suppongo ...
Mr. Xcoder il

12
Ah, la rabbia per valutare contenuti casuali da Internet - bravo! : P
Luke Briggs,

@LukeBriggs Dovrebbe teoricamente essere sicuro ... Voglio dire, il mio computer non è esploso ( ancora ) quindi dovrebbe andare bene, giusto? : P Ma in alternativa potresti usare __import__('ast').literal_evalal posto di evalse davvero volessi: P
HyperNeutrino il

Si rompe su 744?
Draco18s

@ Draco18s Non dovrebbe, perché le virgolette triple non si preoccupano delle virgolette non corrispondenti, e non c'è ;;.
HyperNeutrino,

11

Wolfram Language / Mathematica, 118 117 byte

salvato un byte grazie a numbermanic

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

Spiegazione:

Utilizzare StringTemplateper formare l'URL dall'input.

Import[..., "RawJSON"]importa l'oggetto JSON e lo analizza in un Assocation.

Seleziona il valore per la chiave "alt".

Prendi questo risultato e prova a interpretare la stringa come HTML ( Import[#,"HTML"]). Se ciò non cambia nulla, passa il risultato, se restituisce $Failed. Questo cattura 859 perché

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

risulta in:

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

404 fallisce perché

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

risultati in $Failed.


Quale versione stai usando? Ottengo The Import element "RawJSON" is not present when importing as JSONil 10.0.1.
Julian Wolf,

@totallyhuman Beh, probabilmente non è necessario controllare per 859. (Vedi la condizione di generosità nella domanda)
Decadimento beta

@JulianWolf Sto usando l'11.1.0. Penso che il supporto "RawJSON" sia stato aggiunto in 10.2.
chuy,

4
@totallyhuman Non fa un controllo esplicito, ma è proprio questo il punto ImportString[#,"HTML"].
chuy,

1
@numbermaniac In effetti posso. Non riesco a credere che mi sia mancato, grazie!
chuy,

8

Java 8, 255 176 byte

Grazie a @ OlivierGrégoire per avermi fatto sentire un idiota e con 79 byte di sconto. ;)

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

Sembra troppo pesante ... Ancora pesante, ma "ok" per Java ...

Spiegazione:

  • i->{...} Lambda che funziona come String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() leggi tutto dal dato InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()questo crea un InputStreamriferimento al corpo di risposta di http://xkcd.com/{comic_id}/info.0.jsoncui è la pagina informativa del fumetto desiderato
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Rimuove tutto tranne il testo alternativo (fino alla prima doppia citazione)
  • ritorno implicito

Approccio alternativo più breve, 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")

Questa non è la mia soluzione, quindi non voglio pubblicare questo come primo. Tutti i crediti appartengono a @ OlivierGrégoire.


1
Mancano le tue importazioni! . Inoltre, c'è quasi zero tentativo di giocare a golf questa risposta ...
Olivier Grégoire,

Aggiunto. Poco meno di 2 ^ 8. Almeno la dimensione del mio programma si inserisce in un byte :)
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 byte, attento ai caratteri di taglio dei commenti della SO) E ho appena giocato a golf qui.
Olivier Grégoire,

Oh! Ho pensato che Scanner#useDelimiterritorni vuoto ... Meglio leggere la documentazione la prossima volta;)
Roman Gräf,

1
Ho appena notato che puoi creare la tua Functionclasse che ti consente di lanciare un'eccezione .. Oggi non è il mio giorno.
Roman Gräf,

7

PHP, 89 86 85 byte

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

Restituisce null per 404 e 859

Salva come xkcd.php ed esegui con il numero comico ...

$ php xkcd.php 386

utilizzare $argninvece di $argv[1], _anzichéNULL
Jörg Hülsermann il

@ JörgHülsermann Grazie! Non sapevo di _. $ argn non sembra funzionare però.
Jared Mellentine,

php.net/manual/en/features.commandline.options.php $argn è disponibile se si esegue PHP dalla riga di comando con -Rl' -Fopzione o
Jörg Hülsermann

_non è equivalente a NULLin PHP. Questo script genera un errore relativo _all'essere una costante indefinita.
Andy,

@Andy Se una notifica non è consentita ""è un'alternativa migliore poiché NULLJared qui è un esempio di $argn codegolf.stackexchange.com/questions/114146/…
Jörg Hülsermann

5

PHP 5.3, 280 268 262 261 180 byte


1. Salvate 11 grazie ad alcuni dei suggerimenti di Roman Gräf
2. Salvate 1 byte usando il collegamento http invece di https
3. Salvate altri 6 byte grazie a Kevin_Kinsay
4. Salvate un altro 1 byte con il suggerimento di Andy
5. Una revisione importante:

  • errori soppressi con @ invece di cambiare libxml_use_internal_errors
  • usato al implode(0,file(""))posto di file_get_contents("")(2 byte)
  • spostato la $xdefinizione all'interno diif
  • Usare throw 0invece di lanciare effettivamente un'eccezione (arresta in modo anomalo il programma)
  • con l' @io ora posso omettere la comicLinksostituzione.


Il mio primo tentativo di giocare a golf.

Il DOMDocument si interrompe quando si incontrano dobule ID comicLink, quindi ho dovuto rimuoverli. C'è probabilmente un modo migliore per farlo.

Si blocca quando si tenta di ottenere 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');

2
Benvenuti in PPCG! Penso che puoi rimuovere il test sia $x==404perché l'altro codice fallirà sulla risposta 404 ... Inoltre puoi sostituirlo throw new Exceptioncon una diechiamata e rimuovere le parentesi intorno throw new Exception("")/ dieperché è solo una singola dichiarazione
Roman Gräf

1
Grazie! Non ero sicuro che die () sarebbe stato considerato "gettare un errore";)
Ezenhis il

1
Usa "1" invece di "true" su libxml_use_internal_errors. Probabilmente puoi passare 0 all'eccezione e salvare un preventivo equivalente. La chiusura?> Dovrebbe essere facoltativa.
Kevin_Kinsey,

Le variabili sono interpolate tra virgolette doppie, quindi "http://xkcd.com/".$xpossono diventare "http://xkcd.com/$x"un byte di salvataggio :)
Andy,

A proposito, +1 per l'utilizzo della tecnica di analisi "corretta" (parser XML) rispetto al mio brutto hack regex;)
Kevin_Kinsey

5

Python + xkcd , 54 byte

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

Verifica

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

L'ho appena notato. Bel golf!
Decadimento beta

5

Quello di Python ha già vinto, ma a prescindere ...

bash + curl + sed; 88 ~ 91 heh byte

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

Yay per l'analisi regex JSON!

EDIT NoLongerBreathedIn ha notato (648 giorni nel futuro!) Che questo non è riuscito sul post 2048 a causa di un imprevisto \"nel JSON di quella voce. Il regex è stato aggiornato sopra; era una volta sed 's/.*alt": "\([^"]\+\).*/\1/').

Il printfwrapper gestisce ordinatamente il fatto che i caratteri Unicode sono rappresentati nella \unnnnnotazione:

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

 

Questo non riesce con i post 404 e 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$

Alla $fine dell'output c'è il mio prompt, e quello letteralmente stampato \nimmediatamente prima che faccia parte della stringa printf.

Ho usato deliberatamente printfperché analizzerebbe Unicode e cadrebbe terribilmente su questo post specifico.


Anche barfs nel 2048. Penso che barfs tra virgolette doppie?
NoLongerBreathedIl

Bella presa. Post aggiornato. Guardando il sedbit, puoi vedere che stava cercando alt": "quindi leggere fino a quando non ha trovato a ". Woops, apparentemente ... (Mi chiedo quante di queste soluzioni fallirebbero un test unitario di e̲͕̲̪v̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ ̴͎͉̳̮a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀ ?: P)
i336_

4

Python 2 , 115 106 byte

-8 byte grazie agli ovs. -1 byte grazie a Jonathan Allan.

Ho pensato di mettere una risposta standard in biblioteca.

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

1
lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859]per -8 byte.
Ovs,

1
Dovrebbe funzionare http://troppo salvando un byte.
Jonathan Allan,

4

Bash + curl + jq: 73 66 byte

Risposta più breve che non utilizza una libreria specifica per xkcd. jq è uno strumento per manipolare oggetti json nella shell e viene fornito completo di un linguaggio di analisi per farlo.

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'

Espansione di seguito:

curl -Ls - Interroga, ma sentiti libero di reindirizzare (in questo caso verso il sito https) e non fornire alcun output non correlato.

xkcd.com/$1/info.0.json - Spudoratamente rubato da un'altra risposta.

|jq -r- Esegui jqin modalità "output non elaborato" con il seguente comando.

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

Ora lo script è stato rielaborato per usare il //quale è l'equivalente di a or bin Python, e usiamo a |notper fare in modo che qualsiasi valore vero sia considerato falso, quindi il secondo //può stampare.alt


2

JavaScript (ES6), 177 175 byte

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

Incollalo nella tua console del browser, quindi esegui f(859)o f(404)ecc. - quei due dovrebbero errori nella console, nonostante non siano codificati, gli altri visualizzano.

Primo post tra un po ', scusate se non soddisfa del tutto le regole ...!


Usa x=>invece di (x)=>.
user75200

2

PHP, 160 byte

<? 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);

Aspetta ... questo non è alle specifiche. Riparazione ...
Kevin_Kinsey,

Fisso. Ho dovuto aggiungere circa 50 byte però ... :(
Kevin_Kinsey il

1
puoi rimuovere 7 caratteri rimuovendo l'eco e spostando l'assegnazione $ c all'interno del substr
Einacio

1
@BetaDecay perché non controllare il numero di input dà punti extra
Einacio

1
@BetaDecay bene, uno script che dipende dal contenuto mi sembra mal scritto. Qualsiasi altro titolo che inizia così potrebbe romperlo. Kevin_Kinsey puoi sostituire ENT_QUOTES con il suo valore = 3
Einacio,

1

Perl, 129 167 byte

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

EDIT: Psiche è in realtà

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

Importa la decodifica HTML e l'accesso HTTP, quindi stampa il gruppo corrispondente al (...) in

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

(salvando un po 'omettendo {{Title dalla query)

Per 404 e 859, morte.


Cosa intendi con "gestisce correttamente 859"?
Decadimento beta

@BetaDecay Stampa l'attuale alt-text
archaephyrryx il

1
the program must throw an error when given the numbers 859 or 404
Decadimento beta

Come si definisce "genera un errore"?
archaephyrryx,

Nvm dieè abbastanza corto
archaephyrryx il

1

BASH, 111 108 byte

a = $ (cat) curl -s https://xkcd.com/ $ a / | grep -oP '(? <= Testo del titolo:) ([^}}] *)' [$ a = 404] && echo "$ a non trovato"

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


Per eseguire:
cambia # in numero di fumetti. Esegui dalla riga di comando.

Grazie @Ale per il suggerimento!


Perché leggere dall'input standard usando cat invece di usare solo $ 1 dalla riga di comando? Salverebbe alcuni byte ...
Ale

1

Javascript (ES6), 118 96 94 byte

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

Puoi incollarlo nella console del tuo browser ed eseguirlo f(123). Ma fallo su una pagina che è già su xkcd.com altrimenti vedrai un errore CORS.

Per 404, non riesce con:

Uncaught (promessa) SintassiError: token imprevisto <in JSON nella posizione 0

Per 859, fallisce con:

Uncaught (in promessa) SintassiError: mancante) dopo l'elenco degli argomenti

Aggiornamento: l'ultima versione controlla correttamente il testo alternativo invece di controllare solo 859 e si rade di altri 2 byte.


Purtroppo, ciò fallisce su qualsiasi titolo contenente un apostrofo (ad esempio 1084).
ETHproductions
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.