Сборка неисправного браузера XKCD

75

Вызов

Учитывая номер комикса XKCD, выведите текст заголовка этого комикса (текст при наведении курсора мыши).

Тем не менее, программа должна выдать ошибку, когда даны цифры 859или 404.

правила

Указанный номер всегда будет существующим комиксом (кроме 404).

Ваша программа не должна выдавать ошибку для любых других чисел, кроме 859или 404.

Для справки, комиксов 404не существует и 859это:

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

Укороченные URL запрещены. Вы можете использовать Интернет, чтобы получить текст заголовка.

Примеры

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.

премия

Я назначу награду за самый короткий ответ, который не подходит для комикса 859, потому что он плохо написан вместо проверки номера.

Ваша программа может разбиваться на другие альтернативные тексты (например, 744), при условии, что они имеют несопоставимые скобки, кавычки и т. Д.

выигрыш

Самый короткий код в байтах побеждает.

Бета распад
источник
2
Так как есть другие комиксы с альт-текстами, нарушающими сценарий (см. 744 ), нормально ли это, если программа тоже ломается?
полностью человек
8
@totallyhuman Вы должны были добавить немного-NSFW-предупреждение к этому: P
HyperNeutrino
11
Противоречие в вызове: «не должно выдавать ошибку для любых других чисел, кроме 859или 404» и «может сломаться на других альтернативных текстах».
aschepler
3
@aschepler Последний только для щедрости
Beta Decay
4
@Kzqai Хороший вопрос, но я думаю, что вы, возможно, немного недооцениваете, сколько трафика задействовано в DDOS, а также сколько трафика уже есть на xkcd.com. Я не ожидаю, что трафик, генерируемый ответами, будет значительным по сравнению с любым из них.
трихоплакс

Ответы:

107

Python 2.7 + xkcd , 55 байт

xkcd - это сторонний пакет Python. В Python есть пакет для всего !

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

Для 404: urllib2.HTTPError: HTTP Error 404: Not Found

Для 859: IndexError: list index out of range

Мистер Xcoder
источник
89
Пакет был написан перед этим испытанием и не был написан специально для этого испытания, он просто оказывается очень подходящим.
Draco18s
4
Вау, Python стал еще привлекательнее!
Nat
6
Так совпало, что питон действительно поддерживает import«Ing antigravity.
еще один пользователь
39
Python только Mathematica этот вызов?
Арктур
22

Python 2 + Requests , 104 102 95 94 байта

-2 байта благодаря Эрику Аутгольферу. -1 байт благодаря Джонатану Аллану.

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

Обязательно:

import antigravity

Плохо написанный скрипт, 98 байт

Таким образом, написание плохих сценариев на самом деле сложно сделать намеренно ... Это также нарушает другие комиксы, потому что они содержат кавычки, не уверен, что это нормально.

from requests import*
exec'print "%s"'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt']
totallyhuman
источник
4
Я думаю, что вы можете удалить ,a.
Эрик Outgolfer
1
Вы можете изменить n in[404,859]на n==859, потому что JSON-декодер не работает в 404любом случае.
musicman523
7
... http://можно использовать и здесь, я думаю.
Джонатан Аллан
1
как вы на самом деле запустить это с параметром? Мол, как ты запускаешь безымянную лямбду?
MrZander
1
@MrZander Первая строка - это анонимная лямбда, которую можно назначить для запуска переменной. Например, оба f = lambda n: n * 2; print f(2)или (lambda n: n * 2)(2)напечатают 4.
полностью человек
18

Python 2 + xkcd, 82 байта

Плохо написанный сценарий

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

Добавляет и добавляет ''', что, если текст не содержит ''', не будет ломаться, даже для других кавычек. То есть, за исключением случаев, когда текст содержит ;;, который заменяется на '''(исключая re). Это относится только к 859, и, таким образом, этот код работает 859. :П

Кроме того, никогда не следует evalслучайный интернет-контент, потому что, если он xkcd.getComic(n).altTextкаким-то образом стал '''+__import__('os').system('rm -rf / --no-preserve-root')+''', это может вызвать много плохих вещей. А именно, он удалит все, что доступно non-sudo на компьютере, если вы не запускаете программы codegolf в sudo (также не рекомендуется): P

HyperNeutrino
источник
1
Плохо написана и не для этого теста, 859? Кто-то собирается получить награду, я полагаю ...
Mr. Xcoder
12
Ах, шалость для оценки случайного контента из Интернета - браво! : P
Люк Бриггс
@ LukeBriggs Теоретически это должно быть безопасно ... Я имею в виду, что мой компьютер не взорвался ( пока ), поэтому все должно быть хорошо, верно? : P Но в качестве альтернативы вы можете использовать __import__('ast').literal_evalвместо, evalесли вы действительно хотите: P
HyperNeutrino
Это сломается на 744?
Draco18s
@ Draco18s Не должно быть, потому что тройные кавычки не заботятся о несовпадающих кавычках, а их нет ;;.
HyperNeutrino
11

Wolfram Language / Mathematica, 118 117 байтов

сэкономил байт благодаря Numbermanic

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

Объяснение:

Используйте StringTemplateдля формирования URL из ввода.

Import[..., "RawJSON"]импортирует объект JSON и анализирует его в Assocation.

Выберите значение для ключа "alt".

Возьмите этот результат и попытайтесь интерпретировать строку как HTML ( Import[#,"HTML"]). Если это ничего не меняет, передайте результат, если он вернется $Failed. Это ловит 859, потому что

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

результаты в:

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

404 терпит неудачу, потому что

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

результаты в $Failed.

Чу ý
источник
Какую версию ты используешь? Я получаю The Import element "RawJSON" is not present when importing as JSONна 10.0.1.
Джулиан Вольф
@totallyhuman Ну, это, вероятно, не нужно проверять на 859. (См. условие щедрости в вопросе)
бета-распад
@JulianWolf Я использую 11.1.0. Я думаю, что поддержка "RawJSON" была добавлена ​​в 10.2.
Чу
4
@totallyhuman Это не делает явной проверки, но в этом и заключается суть ImportString[#,"HTML"].
Чу
1
@numbermaniac Действительно, я могу. Не могу поверить, что я пропустил это, спасибо!
Чу
8

Java 8, 255 176 байт

Спасибо @ OlivierGrégoire за то, что заставил меня почувствовать себя идиотом и выбросил 79 байтов. ;)

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

Это кажется слишком тяжелым ... Все еще тяжелым, но "хорошо" для Java ...

Объяснение:

  • i->{...} Лямбда, которая работает как String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() читать все из приведенного InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()это создает InputStreamссылку, тело ответа http://xkcd.com/{comic_id}/info.0.jsonкоторой является информационной страницей нужного комикса.
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Удаляет все, кроме альтернативного текста (до первой двойной кавычки)
  • неявное возвращение

Альтернативный короткий подход, 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")

Это не мое решение, поэтому я не хочу публиковать это как первое. Все кредиты принадлежат @ OlivierGrégoire.

Роман Греф
источник
1
Ваш импорт отсутствует! , Кроме того, есть почти нулевая попытка
Оливье Грегуар
Добавлен. Чуть меньше 2 ^ 8. По крайней мере, размер моей программы умещается в один байт :)
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 байт, осторожно с символами резака SO). И я только что-то играл в гольф здесь.
Оливье Грегуар
Ой! Я думал, что Scanner#useDelimiterвозвращается пусто ... Лучше почитай документы в следующий раз;)
Роман Греф
1
Я только что заметил, что вы можете создать свой собственный Functionкласс, который позволяет бросать исключения. Сегодня не мой день.
Роман Греф
7

PHP 89 86 85 байт

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

Возвращает ноль для 404 и 859

Сохранить как xkcd.php и запустить с комическим номером ...

$ php xkcd.php 386
Джаред Меллентин
источник
использовать $argnвместо $argv[1], _вместоNULL
Йорг Хюльсерманн
@ JörgHülsermann Спасибо! Я не знал о _. $ argn, похоже, не работает, хотя.
Джаред Меллентин
php.net/manual/en/features.commandline.options.php $argn доступен при запуске PHP из командной строки с -Rили -Fвариант
Йорг Hülsermann
_не эквивалентно NULLв PHP. Этот скрипт выдает ошибку о том, _что является неопределенной константой.
Энди
@Andy Если Уведомление не разрешено "", это лучшая альтернатива, так как NULLДжаред здесь - пример для $argn codegolf.stackexchange.com/questions/114146/…
Йорг Хюльсерманн
5

PHP 5.3, 280 268 262 261 180 байт


1. Сохранено 11 благодаря некоторым предложениям Романа Грефа
2. Сохранено 1 байт с использованием http-ссылки вместо https
3. Сохранено еще 6 байтов благодаря Kevin_Kinsay
4. Сохранено еще 1 байт по предложению Энди
5. Основная редакция:

  • подавленные ошибки с @ вместо изменения libxml_use_internal_errors
  • используется implode(0,file(""))вместо file_get_contents("")(2 байта)
  • переместил $xопределение внутриif
  • Использование throw 0вместо фактического создания исключения (это приводит к сбою программы)
  • с @я теперь могу опустить comicLinkзамену.


Моя первая попытка игры в гольф.

DOMDocument ломается, когда сталкивается с идентификатором dobule comicLinks, поэтому мне пришлось удалить их. Вероятно, есть более хороший способ сделать это.

Сбой при попытке получить нет. 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
источник
2
Добро пожаловать в PPCG! Я думаю , что вы можете удалить тест ли $x==404потому , что другой код потерпит неудачу на 404 ответ ... Также вы можете заменить throw new Exceptionна dieвызов и удалить скобки throw new Exception("")/ , dieпотому что это только один оператор
Роман Gräf
1
Спасибо! Я не был уверен, что die () будет считаться "выбросить ошибку";)
Ezenhis
1
Используйте «1» вместо «true» в libxml_use_internal_errors. Вы, вероятно, можете передать 0 в Исключение и сохранить один эквивалент цитаты. Закрытие?> Должно быть необязательным.
Kevin_Kinsey
Переменные интерполируются внутри двойных кавычек, поэтому они "http://xkcd.com/".$xмогут стать "http://xkcd.com/$x"сохранением одного байта :)
Andy
Кстати, +1 за использование «правильной» техники синтаксического анализа (синтаксический анализатор XML), в отличие от моего отвратительного взлома регулярных выражений;)
Kevin_Kinsey
5

Python + xkcd , 54 байта

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

верификация

>>> 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)
Деннис
источник
Я только что заметил это. Хороший гольф!
бета-распад
5

Питон один уже победил, но независимо ...

Баш + Керл + Сед; 88 ~ 91 хех байт

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

Yay для регулярного анализа JSON!

РЕДАКТИРОВАТЬ NoLongerBreathedIn заметил (648 дней в будущем!), Что это не удалось на пост 2048 из-за неожиданного \"в JSON этой записи. Регулярное выражение было обновлено выше; раньше было sed 's/.*alt": "\([^"]\+\).*/\1/').

printfОбертка аккуратно обрабатывает тот факт , что символы Unicode представлены в \unnnnобозначениях:

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

 

Это терпит неудачу с постами 404 и 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$

В $конце вывода отображается моя подсказка, и буквально печатается \nнепосредственно перед тем, как она является частью строки printf.

Я сознательно использовал, printfпотому что он будет анализировать Unicode и ужасно упадет на этом конкретном посте.

i336_
источник
Также barfs на 2048. Я думаю, что это barfs на двойные кавычки?
NoLongerBreathedIn
Хорошо поймал. Сообщение обновлено. Глядя на sedбит, вы можете видеть, что он искал, а alt": "затем читал, пока не нашел ". Woops, по-видимому ... (Интересно, сколько из этих решений не пройдет модульное тестирование e̲͕̲̪v̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ ̴͎͉̳̮a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀ ?: P)
i336_
4

Python 2 , 115 106 байт

-8 байт благодаря овс. -1 байт благодаря Джонатану Аллану.

Просто подумал, что я положу стандартный ответ библиотеки там.

lambda n:[json.load(urllib.urlopen('http://xkcd.com/%d/info.0.json'%n))['alt']][n==859]
import urllib,json
totallyhuman
источник
1
lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859]для -8 байтов.
овс
1
Должно работать с http://сохранением байта.
Джонатан Аллан
4

Bash + curl + jq: 73 66 байт

Самый короткий ответ, который не использует специфичную для xkcd библиотеку. jq - это инструмент для манипулирования объектами json в оболочке, и для этого он поставляется с языком синтаксического анализа.

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'

Расширение ниже:

curl -Ls - Запросить, но не стесняйтесь перенаправить (в данном случае на сайт https) и не давать никаких связанных результатов.

xkcd.com/$1/info.0.json - бесстыдно украден из другого ответа.

|jq -r- Запустите jqв режиме «необработанный вывод» по следующей команде.

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

Теперь скрипт был переработан для использования, //что является эквивалентом a or bв python, и мы используем a, |notчтобы любое истинное значение считалось ложным, поэтому второе //может вывести.alt

Aviator45003
источник
2

JavaScript (ES6), 177 175 байт

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

Вставьте это в консоль браузера, затем выполните f(859)или и f(404)т. Д. - эти два должны произойти с ошибкой в ​​консоли, несмотря на то, что они не жестко запрограммированы, остальные отображаются.

Первое сообщение через некоторое время, извините, если оно не совсем соответствует правилам ...!

Джеймс Торп
источник
Используйте x=>вместо (x)=>.
user75200
2

PHP, 160 байт

<? 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
источник
Подожди ... это не для спецификации. Исправление ...
Kevin_Kinsey
Исправлена. Пришлось добавить около 50 байтов, хотя ... :(
Kevin_Kinsey
1
Вы можете удалить 7 символов, удалив эхо и переместив присвоение $ c внутри подстроки
Einacio
1
@BetaDecay, потому что не проверка введенного номера дает дополнительные очки
Einacio
1
@ BetaDecay хорошо, сценарий, который зависит от содержания, выглядит плохо написанным для меня. Любой другой заголовок, начинающийся как этот, сломал бы это. Kevin_Kinsey вы можете заменить ENT_QUOTES на его значение = 3
Einacio
1

Perl, 129 167 байт

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

РЕДАКТИРОВАТЬ: Психея это на самом деле

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

Импортируйте декодирование HTML и HTTP-доступ, затем напечатайте группу, соответствующую (...) в

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

(немного сэкономив, пропустив {{Title из запроса)

Для 404 и 859 смерть.

archaephyrryx
источник
Что вы подразумеваете под "правильно обрабатывает 859"?
бета-распад
@BetaDecay Он печатает фактический альт-текст
archaephyrryx
1
the program must throw an error when given the numbers 859 or 404
бета-распад
Что означает «выбросить ошибку»?
archaephyrryx
Nvm dieдостаточно короткий
archaephyrryx
1

BASH, 111 108 байт

a = $ (cat) curl -s https://xkcd.com/ $ a / | grep -oP '(? <= текст заголовка:) ([^}}] *)' [$ a = 404] && echo "$ a не найдено"

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


Для запуска:
измените # на номер комикса. Запустите из командной строки.

Спасибо @Ale за предложение!

Silentziler
источник
Зачем читать из стандартного ввода, используя cat вместо $ 1 из командной строки? Это спасло бы несколько байтов ...
Ale
1

Javascript (ES6), 118 96 94 байтов

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

Вы можете вставить это в консоль браузера и запустить f(123). Но сделайте это на странице, которая уже есть на xkcd.com, иначе вы увидите ошибку CORS.

Для 404 это не с:

Uncaught (в обещании) SyntaxError: неожиданный токен <в JSON в позиции 0

Для 859 это терпит неудачу с:

Uncaught (в обещании) SyntaxError: отсутствует) после списка аргументов

Обновление: последняя версия правильно проверяет альтернативный текст, вместо того, чтобы проверять только 859 и сбивает еще 2 байта.

Кристиан Вестербик
источник
К сожалению, это не работает с любым заголовком, содержащим апостроф (например, 1084).
ETHproductions