Construir un navegador XKCD defectuoso

75

Desafío

Dado el número de un cómic XKCD, genera el texto del título de ese cómic (el texto que pasa el mouse).

Sin embargo, el programa debe arrojar un error cuando se le dan los números 859o404 .

Reglas

El número dado siempre será un cómic existente (excepto 404 ).

Su programa no debe arrojar un error para ningún otro número que 859o404 .

Como referencia, el cómic 404no existe y 859es:

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

Los acortadores de URL no están permitidos. Puede usar Internet para obtener el texto del título.

Ejemplos

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.

Generosidad

Otorgaré una recompensa por la respuesta más corta que falla en el cómic 859 porque está mal escrito en lugar de verificar el número.

Su programa puede interrumpirse en otros textos alternativos (como 744) siempre que tengan paréntesis, comillas, etc.

Victorioso

El código más corto en bytes gana.

Decaimiento Beta
fuente
2
Dado que hay otros cómics con textos alternativos que rompen el guión (ver 744 ), ¿está bien si un programa también los rompe?
Totalmente humano
8
@totallyhuman Deberías haber agregado una advertencia ligeramente NSFW a eso: P
HyperNeutrino
11
Contradicción en el desafío: "no debe arrojar un error para ningún otro número que no 859sea 404" y "puede romperse en otros textos alternativos".
aschepler
3
@aschepler Este último es solo para la recompensa
Decaimiento Beta
44
@Kzqai Buena pregunta, pero creo que puede estar subestimando ligeramente la cantidad de tráfico involucrado en un DDOS, y también la cantidad de tráfico que ya tiene xkcd.com. No esperaría que el tráfico generado a partir de las respuestas aquí sea significativo en comparación con ninguno de esos.
trichoplax

Respuestas:

107

Python 2.7 + xkcd , 55 bytes

xkcd es un paquete de Python de terceros. ¡En Python, hay un paquete para todo !

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

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

Para 859: IndexError: list index out of range

Sr. Xcoder
fuente
89
El paquete fue escrito antes de este desafío y no fue escrito específicamente para este desafío, simplemente termina siendo muy apropiado.
Draco18s
44
¡Guau, Python se ha vuelto más atractivo!
Nat
14
@Nat ¡ Únete a nosotros!
jkd
66
Casualmente, Python sí admite import'ing antigravity.
Yet Another User
39
¿Python acaba de Mathematica este desafío?
Arcturus
22

Python 2 + Solicitudes , 104 102 95 94 bytes

-2 bytes gracias a Erik the Outgolfer. -1 byte gracias a Jonathan Allan.

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

Obligatorio:

import antigravity

Escritura mal escrita, 98 bytes

Entonces, escribir scripts pobres es realmente difícil de hacer intencionalmente ... Esto también se rompe en otros cómics porque contienen comillas, no estoy seguro de si eso está bien.

from requests import*
exec'print "%s"'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt']
totalmente humano
fuente
44
Creo que puedes eliminarlo ,a.
Erik the Outgolfer
1
Puede cambiar n in[404,859]a n==859, porque el decodificador JSON falla de 404todos modos.
musicman523
77
... también http://se puede usar aquí, creo.
Jonathan Allan
1
¿Cómo ejecutas esto realmente con un parámetro? ¿Cómo ejecutas una lambda sin nombre?
MrZander
1
@MrZander La primera línea es una lambda anónima que se puede asignar a una variable para que se ejecute. Por ejemplo, ambos f = lambda n: n * 2; print f(2)o (lambda n: n * 2)(2)imprimirán 4.
totalmente humano
18

Python 2 + xkcd, 82 bytes

Escritura mal escrita

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

Anexa y antepone ''', que, a menos que el texto contenga ''', no se romperá, incluso para otras comillas. Es decir, excepto si el texto contiene ;;, que se reemplaza con '''(eliminar re). Esto solo se aplica 859y, por lo tanto, este código se rompe 859. :PAGS

Además, uno nunca debe evalaleatorizar el contenido de Internet, porque si de xkcd.getComic(n).altTextalguna manera se volviera '''+__import__('os').system('rm -rf / --no-preserve-root')+''', causaría que ocurrieran muchas cosas malas. Es decir, eliminaría todo lo que no sea accesible para sudo en la computadora, a menos que ejecute programas codegolf en sudo (tampoco recomendado): P

Hiperneutrino
fuente
1
Mal escrito y falla para ese caso de prueba, 859? Alguien obtendrá una recompensa, supongo ...
Sr. Xcoder
12
Ah, la pena por evaluar contenido aleatorio de Internet: ¡bravo! : P
Luke Briggs
@LukeBriggs Teóricamente debería ser seguro ... Quiero decir, mi computadora no ha explotado ( todavía ), así que debería estar bien, ¿verdad? : P Pero, alternativamente, podría usar __import__('ast').literal_evalen lugar de evalsi realmente quisiera: P
HyperNeutrino
¿Se rompe en 744?
Draco18s
@ Draco18s No debería, porque las comillas triples no se preocupan por las comillas que no coinciden, y no hay ninguna ;;.
HyperNeutrino
11

Wolfram Language / Mathematica, 118117 bytes

guardado un byte gracias a numbermanic

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

Explicación:

Use StringTemplatepara formar la URL a partir de la entrada.

Import[..., "RawJSON"]importa el objeto JSON y lo analiza en un Assocation.

Seleccione el valor para la clave "alt".

Tome este resultado e intente interpretar la cadena como HTML ( Import[#,"HTML"]). Si esto no cambia nada, pase el resultado, si regresa $Failed. Esto atrapa 859 porque

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

resultados en:

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

404 falla porque

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

resultados en $Failed.

chuy
fuente
Qué versión estás usando? Me pongo The Import element "RawJSON" is not present when importing as JSONen 10.0.1.
Julian Wolf
@totallyhuman Bueno, probablemente no sea necesario verificar 859. (Ver la condición de recompensa en la pregunta)
Decaimiento Beta
@JulianWolf Estoy usando 11.1.0. Creo que el soporte "RawJSON" se agregó en 10.2.
chuy
44
@totallyhuman No hace una comprobación explícita, pero de eso se ImportString[#,"HTML"]trata todo.
chuy
1
@numbermaniac De hecho puedo. No puedo creer que me perdí eso, gracias!
chuy
8

Java 8, 255 176 bytes

Gracias a @ OlivierGrégoire por hacerme sentir como un idiota y 79 bytes de descuento. ;)

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

Esto se siente demasiado pesado ... Todavía pesado, pero "está bien" para Java ...

Explicación:

  • i->{...} Lambda que funciona como String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() leer todo de lo dado InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()esto crea un InputStreamque hace referencia al cuerpo de respuesta http://xkcd.com/{comic_id}/info.0.jsoncuya página de información del cómic deseado
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Elimina todo excepto el texto alternativo (hasta la primera comilla doble)
  • retorno implícito

Enfoque alternativo más corto, 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")

Esta no es mi solución, así que no quiero publicar esto como el primero. Todos los créditos pertenecen a @ OlivierGrégoire.

Roman Gräf
fuente
1
¡Tus importaciones faltan! . Además, hay casi cero intento de golf esta respuesta ...
Olivier Grégoire
Adicional. Poco menos de 2 ^ 8. Al menos el tamaño de mi programa cabe en 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 bytes, cuidado con los caracteres de corte de comentarios del SO) Y apenas jugué al golf aquí.
Olivier Grégoire
Oh! Pensé que Scanner#useDelimiterregresaba vacío ... Mejor lea los documentos la próxima vez;)
Roman Gräf
1
Me acabo de dar cuenta de que puedes crear tu propia Functionclase que te permita lanzar Excepción. Hoy no es mi día.
Roman Gräf
7

PHP, 89 86 85 bytes

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

Devuelve nulo para 404 y 859

Guardar como xkcd.php y ejecutar con el número de cómic ...

$ php xkcd.php 386
Jared Mellentine
fuente
utilizar en $argnlugar de $argv[1], en _lugar deNULL
Jörg Hülsermann
@ JörgHülsermann ¡Gracias! No sabía sobre _. Sin embargo, $ argn no parece funcionar.
Jared Mellentine
php.net/manual/en/features.commandline.options.php $argn está disponible si ejecuta PHP desde la línea de comandos con -Ro con la -Fopción
Jörg Hülsermann
_no es equivalente a NULLen PHP. Este script arroja un error sobre _ser una constante indefinida.
Andy
@Andy Si no se permite un Aviso es ""una mejor alternativa ya que NULLJared aquí es un ejemplo para $argn codegolf.stackexchange.com/questions/114146/…
Jörg Hülsermann
5

PHP 5.3, 280 268 262 261 180 bytes


1. Guardado 11 gracias a algunas de las sugerencias de Roman Gräf
2. Guardado 1 byte usando el enlace http en lugar de https
3. Guardado otros 6 bytes gracias a Kevin_Kinsay
4. Guardado otro 1 byte con la sugerencia de Andy
5. Una revisión importante:

  • errores suprimidos con @ en lugar de cambiar libxml_use_internal_errors
  • utilizado en implode(0,file(""))lugar de file_get_contents("")(2 bytes)
  • movió la $xdefinición dentro delif
  • Usar en throw 0lugar de lanzar una excepción (bloquea el programa)
  • con el @ahora puedo omitir el comicLinkreemplazo.


Mi primer intento de jugar al golf.

El DOMDocument se rompe cuando se encuentra con dobule ID comicLinks, así que tuve que eliminarlos. Probablemente haya una mejor manera de hacerlo.

Se bloquea al intentar obtener un 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
fuente
2
Bienvenido a PPCG! Creo que puede eliminar la prueba ya sea $x==404porque el otro código fallará en la respuesta 404 ... También puede reemplazar throw new Exceptionpor una diellamada y eliminar los corchetes throw new Exception("")/ dieporque es solo una declaración
Roman Gräf
1
¡Gracias! No estaba seguro si die () contaría como "lanzar un error";)
Ezenhis
1
Use "1" en lugar de 'verdadero' en libxml_use_internal_errors. Probablemente pueda pasar 0 a la Excepción y guardar una cotización equivalente. ¿Cierre?> Debe ser opcional.
Kevin_Kinsey
Las variables se interpolan dentro de comillas dobles, por lo que "http://xkcd.com/".$xpueden convertirse en "http://xkcd.com/$x"guardar un byte :)
Andy
Por cierto, +1 por usar la técnica de análisis "adecuada" (analizador XML) en lugar de mi truco feo regex;)
Kevin_Kinsey
5

Python + xkcd , 54 bytes

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

Verificación

>>> 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
fuente
Acabo de notar esto. Buen golf!
Beta Decay
5

El Python ya ha ganado, pero independientemente ...

bash + curl + sed; 88 ~ 91 heh bytes

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

¡Yay para el análisis de expresiones JSON!

EDITAR NoLongerBreathedIn notó (¡648 días en el futuro!) Que esto falló en la publicación posterior a 2048 debido a un inesperado \"en el JSON de esa entrada. La expresión regular se ha actualizado anteriormente; lo que solía ser sed 's/.*alt": "\([^"]\+\).*/\1/').

El printfcontenedor maneja perfectamente el hecho de que los caracteres Unicode están representados en \unnnnnotación:

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

 

Esto falla con las publicaciones 404 y 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$

El $final de la salida es mi indicador, y se imprime literalmente \ninmediatamente antes de que sea parte de la cadena printf.

Lo usé deliberadamente printfporque analizaría Unicode y se caería terriblemente en esta publicación específica.

i336_
fuente
También barfs en 2048. Creo que barfs en comillas dobles?
NoLongerBreathedIn
Buena atrapada. Publicación actualizada. Mirando el sedbit, puede ver que estaba buscando y alt": "luego leyendo hasta que encontró un ". Woops, aparentemente ... (Me pregunto cuántas de estas soluciones fallarían una prueba unitaria de e̲͕̲̪v̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ ̴͎͉̳̮a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀ ?: P)
i336_
4

Python 2 , 115106 bytes

-8 bytes gracias a los ovs. -1 byte gracias a Jonathan Allan.

Solo pensé en poner una respuesta estándar de la biblioteca por ahí.

lambda n:[json.load(urllib.urlopen('http://xkcd.com/%d/info.0.json'%n))['alt']][n==859]
import urllib,json
totalmente humano
fuente
1
lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859]para -8 bytes.
ovs
1
Debería funcionar http://ahorrando demasiado un byte.
Jonathan Allan
4

Bash + curl + jq: 73 66 bytes

La respuesta más corta que no utiliza una biblioteca específica de xkcd. jq es una herramienta para manipular objetos json en el shell, y viene completo con un lenguaje de análisis para hacerlo.

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'

Expansión a continuación:

curl -Ls - Consulta, pero no dudes en redirigir (en este caso al sitio https) y no dar resultados no relacionados.

xkcd.com/$1/info.0.json - Desvergonzadamente robado de otra respuesta.

|jq -r- Ejecute jqen modo "salida sin formato" con el siguiente 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

Ahora el guión ha sido modificado para usarlo, //que es el equivalente de a or bpython, y usamos a |notpara hacer que cualquier valor verdadero se considere falso, por lo que el segundo //puede imprimir.alt

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

Pegue esto en la consola de su navegador, luego ejecute f(859)o f(404)etc., esos dos deberían aparecer en la consola, a pesar de no estar codificados, los otros se muestran.

Primera publicación en un tiempo, lo siento si no cumple con las reglas ...!

James Thorpe
fuente
Usar en x=>lugar de (x)=>.
user75200
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
fuente
Espera ... esto no es espec. Fixing ...
Kevin_Kinsey
Fijo. Sin embargo, tuve que agregar unos 50 bytes ... :(
Kevin_Kinsey
1
puedes eliminar 7 caracteres eliminando el eco y moviendo la asignación de $ c dentro del substr
Einacio
1
@BetaDecay porque no verificar el número de entrada da puntos extra
Einacio
1
@BetaDecay bueno, un script que depende del contenido me parece mal escrito. Cualquier otro título que comience así lo rompería. Kevin_Kinsey puede reemplazar ENT_QUOTES por su valor = 3
Einacio
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>/)

EDITAR: Psique es en realidad

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

Importe la decodificación HTML y el acceso HTTP, luego imprima el grupo que coincida con (...) en

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

(ahorrando un poco al omitir {{Title de la consulta)

Para 404 y 859, muerte.

Archaephyrryx
fuente
¿Qué quiere decir con "maneja adecuadamente 859"?
Beta Decay
@BetaDecay Imprime el texto alternativo real
archaephyrryx
1
the program must throw an error when given the numbers 859 or 404
Beta Decay
¿Cómo se define "arrojar un error"?
archaephyrryx
Nvm diees lo suficientemente corto
archaephyrryx
1

BASH, 111 108 bytes

a = $ (cat) curl -s https://xkcd.com/ $ a / | grep -oP '(? <= Texto del título:) ([^}}] *)' [$ a = 404] && echo "$ a no encontrado"

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


Para ejecutar:
cambie # a número de cómic. Ejecutar desde la línea de comando.

Gracias @Ale por la sugerencia!

Silentziler
fuente
¿Por qué leer desde la entrada estándar usando cat en lugar de solo usar $ 1 desde la línea de comando? Ahorraría algunos bytes ...
Ale
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}')`))

Puede pegar eso en la consola de su navegador y ejecutar f(123) . Pero hazlo en una página que ya está en xkcd.com o verás un error CORS.

Para 404, falla con:

Sin capturar (en promesa) SyntaxError: token inesperado <en JSON en la posición 0

Para 859, falla con:

Sin capturar (en promesa) SyntaxError: falta) después de la lista de argumentos

Actualización: la última versión verifica correctamente el texto alternativo en lugar de verificar solo 859 y recortes de otros 2 bytes.

Christiaan Westerbeek
fuente
Lamentablemente, esto falla en cualquier texto de título que contenga un apóstrofe (por ejemplo, 1084).
ETHproducciones