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.


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


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


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']

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


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.


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.


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

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

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)

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.


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

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


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 ...!


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

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.


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!


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.


Infelizmente, isso falha em qualquer texto de título contendo um apóstrofo (por exemplo, 1084).
ETHproductions
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.