Crie um navegador XKCD com defeito

75

Desafio

Dado o número de uma história em quadrinhos do XKCD, produza o texto do título dessa história em quadrinhos (o texto do mouseover).

No entanto, o programa deve gerar um erro quando receber os números 859ou 404.

Regras

O número fornecido sempre será uma história em quadrinhos existente (exceto 404).

Seu programa não deve gerar um erro para outros números que não sejam 859ou 404.

Para referência, o quadrinho 404não existe e 859é:

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

Os encurtadores de URL não são permitidos. Você pode usar a internet para obter o texto do título.

Exemplos

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.

Recompensa

Atribuirei uma recompensa à resposta mais curta que falhar no quadrinho 859 porque está mal escrito, em vez de procurar o número.

Seu programa pode ser interrompido por outros textos alternativos (como o 744), desde que entre parênteses, aspas, etc.

Ganhando

O menor código em bytes vence.

Beta Decay
fonte
2
Como existem outros quadrinhos com textos alternativos que quebram scripts (veja 744 ), está tudo bem se um programa quebrar nesses também?
totallyhuman
8
@totallyhuman Você deveria ter adicionado um aviso um pouco NSFW a isso: P
HyperNeutrino
11
Contradição no desafio: "não deve gerar um erro para nenhum outro número que não 859seja 404" ou "e" pode quebrar em outros textos alternativos ".
Aschepler
3
@aschepler O último é apenas para a recompensa
Decay Beta
4
@ Kzqai Boa pergunta, mas acho que você pode estar subestimando um pouco o tráfego envolvido em um DDOS e também o tráfego que o xkcd.com já possui. Eu não esperaria que o tráfego gerado a partir das respostas aqui fosse significativo em comparação com qualquer um deles.
Trichoplax

Respostas:

107

Python 2.7 + xkcd , 55 bytes

O xkcd é um pacote Python de terceiros. No Python, há um pacote para tudo !

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

Mr. Xcoder
fonte
89
O pacote foi escrito antes deste desafio e não foi escrito especificamente para esse desafio, mas acaba sendo altamente apropriado.
Draco18s
4
Uau, o Python ficou mais atraente!
Nat
14
@ Nat Venha se juntar a nós!
Jkd 01/07/19
6
Coincidentemente, o python realmente suporta import'ing antigravity.
Outro usuário
39
Python acabou de Mathematica esse desafio?
Arcturus
22

Solicitações Python 2 + , 104 102 95 94 bytes

-2 bytes graças a Erik, o Outgolfer. -1 byte graças a Jonathan Allan.

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

Obrigatório:

import antigravity

Script mal escrito, 98 bytes

Então, escrever scripts ruins é realmente difícil de fazer intencionalmente ... Isso também ocorre em outros quadrinhos porque eles contêm aspas, não tenho certeza se está tudo bem.

from requests import*
exec'print "%s"'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt']
totalmente humano
fonte
4
Eu acho que você pode remover ,a.
Erik the Outgolfer
1
Você pode mudar n in[404,859]para n==859, porque o decodificador JSON falha de 404qualquer maneira.
musicman523
7
... http://pode ser usado aqui também, eu acho.
Jonathan Allan
1
como você realmente executa isso com um parâmetro? Como, como você administra uma lambda sem nome?
MrZander
1
@MrZander A primeira linha é uma lambda anônima que pode ser atribuída a uma variável a ser executada. Por exemplo, tanto f = lambda n: n * 2; print f(2)ou (lambda n: n * 2)(2)imprimirá 4.
totallyhuman
18

Python 2 + xkcd, 82 bytes

Script mal escrito

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

Anexos e anexos ''', que, a menos que o texto contenha ''', não serão interrompidos, mesmo para outras aspas. Ou seja, exceto se o texto contiver ;;, que será substituído por '''(eliminando re). Isso só se aplica 859e, portanto, esse código é interrompido 859. : P

Além disso, nunca se deve ter evalconteúdo aleatório na Internet, porque, de xkcd.getComic(n).altTextalguma forma '''+__import__('os').system('rm -rf / --no-preserve-root')+''', isso causaria muitas coisas ruins. Ou seja, ele excluiria tudo o que é acessível por não sudo no computador, a menos que você execute programas codegolf no sudo (também não recomendado): P

HyperNeutrino
fonte
1
Mal escrito e falha nesse caso de teste 859? Alguém está indo para obter uma recompensa, eu suponho ...
Mr. Xcoder
12
Ah, o segredo para avaliar conteúdo aleatório da internet - bravo! : P
Luke Briggs
@LukeBriggs Deveria teoricamente ser seguro ... quero dizer, meu computador não explodiu ( ainda ), então deve ficar bem, certo? : P Mas alternativamente você pode utilizar __import__('ast').literal_evalno lugar de evalse você realmente queria: P
HyperNeutrino
Ele quebra no 744?
precisa saber é o seguinte
@ Draco18s Não deveria, porque as aspas triplas não se importam com as aspas incompatíveis, e não há ;;.
21717 HyperNeutrino
11

Wolfram Language / Mathematica, 118 117 bytes

salvou um byte graças ao numbermanic

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

Explicação:

Use StringTemplatepara formar o URL a partir da entrada.

Import[..., "RawJSON"]importa o objeto JSON e analisa-lo em um Assocation.

Selecione o valor para a chave "alt".

Pegue esse resultado e tente interpretar a string como HTML ( Import[#,"HTML"]). Se isso não mudar nada, repasse o resultado, se ele retornar $Failed. Isso pega 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"]

resulta em:

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

404 falha porque

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

resulta em $Failed.

chuy
fonte
Qual versão você está usando? Eu The Import element "RawJSON" is not present when importing as JSONentro no 10.0.1.
Julian Lobo
@totallyhuman Bem, provavelmente não precisa procurar 859. (Veja a condição de recompensa na pergunta)
Deterioração beta
@JulianWolf Estou usando o 11.1.0. Eu acho que o suporte "RawJSON" foi adicionado na 10.2.
chuy
4
@totallyhuman Não faz uma verificação explícita, mas é disso que ImportString[#,"HTML"]se trata.
chuy
1
@numbermaniac De fato eu posso. Não acredito que perdi isso, obrigado!
chuy
8

Java 8, 255 176 bytes

Agradeço ao @ OlivierGrégoire por me fazer sentir como um idiota e com 79 bytes de folga. ;)

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

Isso parece muito pesado ... Ainda pesado, mas "ok" para java ...

Explicação:

  • i->{...} Lambda que funciona como String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() leia tudo desde o dado InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream() isso cria um InputStream que referencia o corpo de resposta do http://xkcd.com/{comic_id}/info.0.jsonqual é a página de informações do quadrinho desejado
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Remove tudo, exceto o texto alternativo (até a primeira aspas duplas)
  • retorno implícito

Abordagem alternativa mais curta, 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 não é a minha solução, por isso não quero postar isso como o primeiro. Todos os créditos pertencem a @ OlivierGrégoire.

Roman Gräf
fonte
1
Suas importações estão faltando! . Além disso, há quase zero tentativa de golf esta resposta ...
Olivier Grégoire
Adicionado. Um pouco menos de 2 ^ 8. Pelo menos o tamanho do meu programm se encaixa em um 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 com os caracteres do cortador de comentários do SO) E eu mal joguei nada aqui.
Olivier Grégoire
Oh! Eu pensei que Scanner#useDelimiterretornos nulos ... É melhor ler os documentos da próxima vez;)
Roman Gräf 30/06
1
Acabei de notar que você pode criar sua própria Functionclasse que permite lançar a exceção. Hoje não é o meu dia.
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;

Retorna nulo para 404 e 859

Salve como xkcd.php e corra com o número cômico ...

$ php xkcd.php 386
Jared Mellentine
fonte
use em $argnvez de $argv[1], em _vez deNULL
Jörg Hülsermann
@ JörgHülsermann Obrigado! Eu não sabia sobre _. O $ argn parece não funcionar.
Jared Mellentine
php.net/manual/en/features.commandline.options.php $argn está disponível se você executar o PHP a partir da linha de comando com -Ra -Fopção ou
Jörg Hülsermann 30/17
_não é equivalente NULLem PHP. Este script gera um erro sobre _ser uma constante indefinida.
Andy
@Andy Se uma Notificação não é permitido ""é uma alternativa melhor como NULLJared aqui é um exemplo para $argn codegolf.stackexchange.com/questions/114146/...
Jörg Hülsermann
5

PHP 5.3, 280 268 262 261 180 bytes


1. Economizou 11 graças a algumas sugestões de Roman Gräf
2. Economizou 1 byte usando o link http em vez de https
3. Economizou outros 6 bytes graças a Kevin_Kinsay
4. Economizou outro byte com a sugestão de Andy
5. Uma revisão importante:

  • erros suprimidos com @ em vez de alterar libxml_use_internal_errors
  • usado em implode(0,file(""))vez defile_get_contents("") (2 bytes)
  • mudou a $xdefinição dentro doif
  • Usando em throw 0vez de realmente lançar uma exceção (ele trava o programa)
  • com o @agora eu posso omitir a comicLinksubstituição.


Minha primeira tentativa no golfe.

O DOMDocument quebra quando encontra o ID de dobule comicLinks, então eu tive que removê-los. Provavelmente existe uma maneira melhor de fazer isso.

Falha ao tentar não. 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
fonte
2
Bem-vindo ao PPCG! Eu acho que você pode remover o teste se $x==404porque o outro código irá falhar na resposta 404 ... Além disso, você pode substituir throw new Exceptionpor uma diechamada e remover os suportes em torno de throw new Exception("")/ dieporque é apenas uma única instrução
Roman Gräf
1
Obrigado! Eu não tinha certeza se die () contaria como "lançar um erro";)
Ezenhis
1
Use "1" em vez de 'true' em libxml_use_internal_errors. Provavelmente você pode passar 0 para a exceção e salvar uma cotação equivalente. Fechar?> Deve ser opcional.
305177 Kevin_Kinsey
As variáveis são interpolados dentro de aspas, por isso "http://xkcd.com/".$xpode se tornar "http://xkcd.com/$x"salvando um byte :)
Andy
BTW, +1 para o uso "apropriado" técnica de análise (parser XML), em oposição ao meu corte regex feio;)
Kevin_Kinsey
5

Python + xkcd , 54 bytes

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

Verificação

>>> 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
fonte
Acabei de perceber isso. Bom golfe!
Beta Decay
5

O Python já venceu, mas independentemente ...

bash + ondulação + sed; 88 ~ 91 heh bytes

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

Yay para regex JSON análise!

EDIT NoLongerBreathedIn observou (648 dias no futuro!) Que isso falhou no pós 2048 devido a um inesperado \"no JSON dessa entrada. O regex foi atualizado acima; costumava ser sed 's/.*alt": "\([^"]\+\).*/\1/').

O printfwrapper lida perfeitamente com o fato de que caracteres Unicode são representados na \unnnnnotação:

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

 

Isso falha nas postagens 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$

O $final da saída é o meu prompt, e o impresso literalmente\n imediatamente antes de fazer parte da string printf.

Eu usei deliberadamente printfporque ele analisaria o Unicode e cairia muito sobre esse post específico.

i336_
fonte
Também vomita em 2048. Acho que vomita entre aspas duplas?
NoLongerBreathedIn
Boa pegada. Postagem atualizada. Olhando para o sedbit, você pode ver que ele estava procurando e alt": "depois lendo até encontrar um ". Woops, aparentemente ... (Gostaria de saber quantas dessas soluções seriam reprovadas em um teste de unidade de e̲͕̲̪v̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ ̴͎͉̳̮a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀ ?: P)
i336_
4

Python 2 , 115 106 bytes

-8 bytes graças a ovs. -1 byte graças a Jonathan Allan.

Só pensei em colocar uma resposta padrão da biblioteca lá fora.

lambda n:[json.load(urllib.urlopen('http://xkcd.com/%d/info.0.json'%n))['alt']][n==859]
import urllib,json
totalmente humano
fonte
1
lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859]para -8 bytes.
ovs 30/06
1
Deve funcionar com http://muito salvar um byte.
Jonathan Allan
4

Bash + ondulação + jq: 73 66 bytes

Resposta mais curta que não usa uma biblioteca específica do xkcd. O jq é uma ferramenta para manipular objetos json no shell, e vem completo com uma linguagem de análise para fazer isso.

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'

Expansão abaixo:

curl -Ls - Consulte, mas sinta-se à vontade para redirecionar (neste caso para o site https) e não dê saída não relacionada.

xkcd.com/$1/info.0.json - Vergonhosamente roubado de outra resposta.

|jq -r- Execute jqno modo "saída bruta" no seguinte 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

Agora, o script foi re-trabalhado para usar //o equivalente a or bem python, e usamos a |notpara fazer com que qualquer valor verdadeiro seja considerado falso, para que o segundo //possa ser impresso.alt

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

Cole isso no console do navegador, execute f(859)ou f(404)etc - esses dois erros no console, apesar de não serem codificados, os outros são exibidos.

Primeiro post em um tempo, desculpe se ele não atende às regras ...!

James Thorpe
fonte
Use em x=>vez de (x)=>.
precisa saber é o seguinte
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
fonte
Espere ... isso não é especificação. Corrigindo ...
Kevin_Kinsey
Fixo. No entanto, tive que adicionar cerca de 50 bytes ... :(
Kevin_Kinsey
1
você pode remover 7 caracteres removendo o eco e movendo o $ c atribuir dentro do substr
Einacio
1
@BetaDecay porque não verificar o número de entrada fornece pontos extras
Einacio
1
@BetaDecay bem, um script que depende do conteúdo parece mal escrito para mim. Qualquer outro título começando assim iria quebrá-lo. Kevin_Kinsey você pode substituir ENT_QUOTES por seu valor = 3
Einacio 30/06
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 é realmente

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 a decodificação HTML e o acesso HTTP e imprima o grupo correspondente ao (...)

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

(economizando um pouco, omitindo {{Title a consulta)

Para 404 e 859, morte.

archaephyrryx
fonte
O que você quer dizer com "manipula adequadamente o 859"?
Beta Decay
@BetaDecay Ela imprime o real alt-text
archaephyrryx
1
the program must throw an error when given the numbers 859 or 404
Beta Decay
O que é "lançar um erro" definido como?
Archaephyrryx
Nvm dieé curto o suficiente
archaephyrryx
1

BATER, 111 108 bytes

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

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


Para executar:
altere # para o número de quadrinhos. Executar a partir da linha de comando.

Obrigado @Ale pela sugestão!

Silentziler
fonte
Por que ler da entrada padrão usando cat em vez de apenas $ 1 na linha de comando? Ele iria salvar alguns 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}')`))

Você pode colar isso no console do navegador e executar f(123). Mas faça isso em uma página que já está no xkcd.com ou você verá um erro de CORS.

Para 404, ele falha com:

Não detectado (na promessa) SyntaxError: token inesperado <no JSON na posição 0

Para 859, ele falha com:

Não detectado (em promessa) SyntaxError: ausente) após a lista de argumentos

Atualização: a versão mais recente verifica corretamente o texto alternativo em vez de verificar apenas 859 e raspar outros 2 bytes.

Christiaan Westerbeek
fonte
Infelizmente, isso falha em qualquer texto de título contendo um apóstrofo (por exemplo, 1084).
ETHproductions