Zbuduj wadliwą przeglądarkę XKCD

75

Wyzwanie

Biorąc pod uwagę numer komiksu XKCD, wypisz tekst tytułowy tego komiksu (tekst najechania myszą).

Jednak program musi zgłosić błąd po podaniu liczb 859lub 404.

Zasady

Podana liczba będzie zawsze istniejącym komiksem (z wyjątkiem 404).

Twój program nie może zgłaszać błędów dla innych liczb niż 859lub 404.

Dla porównania, komiks 404nie istnieje i 859jest:

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

Skracacze adresów URL są niedozwolone. Możesz użyć Internetu, aby uzyskać tytuł.

Przykłady

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.

Hojność

Przyznam nagrodę za najkrótszą odpowiedź, która nie powiedzie się w komiksie 859, ponieważ jest źle napisany zamiast sprawdzania numeru.

Twój program może się łamać na innych tekstach alternatywnych (takich jak 744), pod warunkiem, że mają niepasujące nawiasy, cudzysłowy itp.

Zwycięski

Najkrótszy kod w bajtach wygrywa.

Rozpad beta
źródło
2
Ponieważ istnieją inne komiksy z łamanymi skryptami tekstami alternatywnymi (patrz 744 ), czy jest w porządku, jeśli program też się na nich psuje?
totalnie ludzki,
8
@totallyhuman Powinieneś dodać do tego nieco ostrzeżenie NSFW: P
HyperNeutrino
11
Sprzeczność w wyzwaniu: „nie wolno rzucać błędem dla żadnych innych liczb niż 859lub 404” i „może złamać inne teksty alternatywne”.
aschepler
3
@aschepler Ten ostatni jest tylko dla nagrody
Beta Decay
4
@Kzqai Dobre pytanie, ale myślę, że możesz nie doceniać, ile ruchu jest zaangażowane w DDOS, a także ile ruchu już ma xkcd.com. Nie spodziewałbym się, że ruch generowany z odpowiedzi tutaj będzie znaczący w porównaniu do któregokolwiek z nich.
trichoplax

Odpowiedzi:

107

Python 2.7 + xkcd , 55 bajtów

xkcd to pakiet Pythona innej firmy. W Pythonie jest pakiet na wszystko !

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

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

Dla 859: IndexError: list index out of range

Pan Xcoder
źródło
89
Pakiet został napisany przed tym wyzwaniem i nie został napisany specjalnie dla tego wyzwania, po prostu jest bardzo odpowiedni.
Draco18s
4
Wow, Python stał się bardziej atrakcyjny!
Nat
6
Przypadkowo, pyton rzeczywiście wspierać import„ing antigravity.
Yet Another User
39
Czy Python właśnie Mathematica to wyzwanie?
Arcturus,
22

Python 2 + Requests , 104 102 95 94 bajtów

-2 bajty dzięki Erikowi Outgolfer. -1 bajt dzięki Jonathan Allan.

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

Obowiązkowy:

import antigravity

Źle napisany skrypt, 98 bajtów

Tak więc pisanie kiepskich skryptów jest naprawdę trudne do umyślnego ... To również psuje inne komiksy, ponieważ zawierają cytaty, nie jestem pewien, czy to w porządku.

from requests import*
exec'print "%s"'%get('http://xkcd.com/%d/info.0.json'%input()).json()['alt']
całkowicie ludzki
źródło
4
Myślę, że możesz to usunąć ,a.
Erik the Outgolfer
1
Możesz zmienić n in[404,859]na n==859, ponieważ i tak dekoder JSON zawiedzie 404.
musicman523
7
... http://myślę, że tutaj też można go użyć.
Jonathan Allan
1
jak faktycznie uruchamiasz to z parametrem? Jak prowadzisz bezimienną lambdę?
MrZander
1
@MrZander Pierwszy wiersz to anonimowa lambda, którą można przypisać do zmiennej, która ma być uruchomiona. Na przykład oba drukują f = lambda n: n * 2; print f(2)lub (lambda n: n * 2)(2)wydrukują 4.
całkowicie ludzki
18

Python 2 + xkcd, 82 bajty

Źle napisany skrypt

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

Dołącza i zastępuje ''', które, o ile tekst nie zawiera ''', nie będą łamane, nawet w przypadku innych znaków cudzysłowu. To znaczy, z wyjątkiem sytuacji, gdy tekst zawiera ;;, który zostaje zastąpiony '''(eliminujący re). Dotyczy to tylko 859i dlatego ten kod się zrywa 859. : P

Ponadto, nigdy nie należy evallosowo wybierać treści internetowych, ponieważ gdyby tak się xkcd.getComic(n).altTextstało '''+__import__('os').system('rm -rf / --no-preserve-root')+''', spowodowałoby to wiele złych rzeczy. Mianowicie, usunąłby wszystko, co jest dostępne dla non-sudo na komputerze, chyba że uruchamiasz programy codegolf w sudo (również niezalecane): P

HyperNeutrino
źródło
1
Źle napisany i nie spełnia tego warunku testowego 859? Przypuszczam, że ktoś dostanie nagrodę ...
Pan Xcoder
12
Ach, żądza odkrywania losowych treści z Internetu - brawo! : P
Luke Briggs
@LukeBriggs Teoretycznie powinno to być bezpieczne ... Mam na myśli, że mój komputer nie wybuchł ( jeszcze ), więc powinno być dobrze, prawda? : P Ale alternatywnie możesz użyć __import__('ast').literal_evalzamiast, evaljeśli naprawdę chcesz: P
HyperNeutrino
Czy psuje się na 744?
Draco18s,
@ Draco18s Nie powinno tak być, ponieważ potrójne cytaty nie dbają o niedopasowane cytaty i nie ma ;;.
HyperNeutrino,
11

Wolfram Language / Mathematica, 118 117 bajtów

zapisano bajt dzięki numeryce

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

Wyjaśnienie:

Użyj, StringTemplateaby utworzyć adres URL na podstawie danych wejściowych.

Import[..., "RawJSON"]importuje obiekt JSON i analizuje go w pliku Assocation.

Wybierz wartość dla klucza "alt".

Weź ten wynik i spróbuj zinterpretować ciąg jako HTML ( Import[#,"HTML"]). Jeśli to nie zmieni niczego, wynik przechodzi, jeśli się zwraca $Failed. Łapie to 859, ponieważ

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

prowadzi do:

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

404 zawodzi, ponieważ

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

powoduje w $Failed.

chuy
źródło
Jakiej wersji używasz? Wchodzę The Import element "RawJSON" is not present when importing as JSONna 10.0.1.
Julian Wolf
@ totalniehuman Cóż, prawdopodobnie nie trzeba sprawdzać 859. (Zobacz warunek nagrody w pytaniu)
Beta Decay
@JulianWolf Używam 11.1.0. Myślę, że wsparcie „RawJSON” zostało dodane w 10.2.
chuy
4
@totallyhuman Nie wykonuje jawnej kontroli, ale o to ImportString[#,"HTML"]właśnie chodzi.
chuy
1
@numbermaniac Rzeczywiście mogę. Nie mogę uwierzyć, że to przegapiłem, dzięki!
chuy
8

Java 8, 255 176 bajtów

Dzięki @ OlivierGrégoire za to, że poczułam się jak idiotka i 79 bajtów wolnego. ;)

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

To wydaje się zbyt ciężkie ... Wciąż ciężkie, ale „w porządku” dla java…

Wyjaśnienie:

  • i->{...} Lambda, która działa jak String <name>(int i) throws Exception
  • new java.util.Scanner(...).setDelimiter("\\a").next() przeczytaj wszystko z podanego InputStream
    • new java.net.URL("http://xkcd.com/"+i+"/info.0.json").openStream()tworzy to InputStreamodwołanie, którego treść odpowiedzi http://xkcd.com/{comic_id}/info.0.jsonjest stroną informacyjną żądanego komiksu
    • replaceFirst(".*\"alt\": \"","").replaceFirst("\".*","") Usuwa wszystko oprócz tekstu alternatywnego (do pierwszego podwójnego cudzysłowu)
  • domniemany zwrot

Alternatywne krótsze podejście, 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")

To nie jest moje rozwiązanie, więc nie chcę tego publikować jako pierwszego. Wszystkie kredyty należą do @ OlivierGrégoire.

Roman Gräf
źródło
1
Brakuje Twojego importu! . Poza tym prawie nie ma próby gry w golfa na tę odpowiedź ...
Olivier Grégoire
Dodany. Nieco poniżej 2 ^ 8. Przynajmniej rozmiar mojego programu mieści się w jednym bajcie :)
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 bajtów, uważaj na postacie z komentarza SO) A ja ledwo grałem tutaj w golfa.
Olivier Grégoire
O! Myślałem, że Scanner#useDelimiterpowraca nieważne ... Lepiej przeczytaj dokumenty następnym razem;)
Roman Gräf
1
Zauważyłem, że możesz stworzyć własną Functionklasę, która pozwoli ci wprowadzić wyjątek. Dzisiaj nie jest mój dzień.
Roman Gräf
7

PHP, 89 86 85 bajtów

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

Zwraca null dla 404 i 859

Zapisz jako xkcd.php i uruchom z numerem komiksu ...

$ php xkcd.php 386
Jared Mellentine
źródło
użyj $argnzamiast $argv[1], _zamiastNULL
Jörg Hülsermann
@ JörgHülsermann Thanks! Nie wiedziałem o _. $ argn nie wydaje się jednak działać.
Jared Mellentine
php.net/manual/en/features.commandline.options.php $argn jest dostępny, jeśli uruchamiasz PHP z wiersza poleceń z opcją -Rlub-F
Jörg Hülsermann
_nie jest równoważne z NULLPHP. Ten skrypt zgłasza błąd dotyczący _niezdefiniowanej stałej.
Andy
@Andy Jeśli powiadomienie nie jest dozwolone, ""jest lepszą alternatywą, ponieważ NULLJared tutaj jest przykładem dla $argn codegolf.stackexchange.com/questions/114146/…
Jörg Hülsermann
5

PHP 5.3, 280 268 262 261 180 bajtów


1. Zaoszczędzono 11 dzięki niektórym sugestiom Romana Gräfa
2. Zaoszczędziłem 1 bajt, używając łącza http zamiast https
3. Zaoszczędziłem kolejne 6 bajtów dzięki Kevin_Kinsay
4. Zaoszczędziłem kolejny 1 bajt dzięki sugestii Andy'ego 5. Ważna
zmiana:

  • pomijane błędy za pomocą @ zamiast zmiany libxml_use_internal_errors
  • użyte implode(0,file(""))zamiast file_get_contents("")(2 bajty)
  • przeniesiono $xdefinicję doif
  • Używanie throw 0zamiast faktycznego zgłaszania wyjątku (powoduje awarię programu)
  • z @I teraz mogę pominąć comicLinkzamianę.


Moja pierwsza próba gry w golfa.

DOMDocument pęka, gdy napotyka comicLinks z identyfikatorem dobule, więc musiałem je usunąć. Prawdopodobnie jest to lepszy sposób.

Awarie podczas próby uzyskania nie. 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
źródło
2
Witamy w PPCG! Myślę, że można usunąć test, czy $x==404dlatego, że inny kod nie powiedzie się od odpowiedzi 404 ... Ponadto można zastąpić throw new Exceptionprzez dierozmowy i usuń nawiasy wokół throw new Exception("")/ diebo jest tylko jedno stwierdzenie
Roman Gräf
1
Dzięki! Nie byłem pewien, czy die () liczy się jako „wyrzucenie błędu”;)
Ezenhis
1
Użyj „1” zamiast „true” na libxml_use_internal_errors. Prawdopodobnie możesz przekazać 0 do wyjątku i zapisać jeden ekwiwalent wyceny. Zamknięcie?> Powinno być opcjonalne.
Kevin_Kinsey
Zmienne są interpolowane w podwójnych cudzysłowach, więc "http://xkcd.com/".$xmożna "http://xkcd.com/$x"zapisać jeden bajt :)
Andy
BTW, +1 za użycie „właściwej” techniki parsowania (parser XML) w przeciwieństwie do mojego brzydkiego hackowania wyrażenia regularnego;)
Kevin_Kinsey
5

Python + xkcd , 54 bajty

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

Weryfikacja

>>> 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
źródło
Właśnie to zauważyłem. Niezły golf!
Beta Decay
5

Python już wygrał, ale niezależnie od ...

bash + curl + sed; 88 ~ 91 heh bajtów

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

Tak, parsowanie wyrażenia regularnego JSON!

EDYCJA NoLongerBreathedIn zauważyła (648 dni w przyszłość!), Że nie powiodło się to po 2048 roku z powodu nieoczekiwanego \"JSON tego wpisu. Wyrażenie regularne zostało zaktualizowane powyżej; kiedyś tak było sed 's/.*alt": "\([^"]\+\).*/\1/').

printfWrapper zgrabnie radzi sobie fakt, że znaki Unicode są reprezentowane w \unnnnnotacji:

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

 

Nie udaje się to z postami 404 i 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$

Na $końcu danych wyjściowych znajduje się mój monit i dosłownie wydrukowany \nbezpośrednio przed umieszczeniem go w łańcuchu printf.

Celowo użyłem, printfponieważ analizowałby Unicode i strasznie przewracał się w tym konkretnym poście.

i336_
źródło
Również barfs w 2048 roku. Myślę, że to barfs w podwójnych cudzysłowach?
NoLongerBreathedIn
Dobry chwyt. Opublikowana aktualizacja. Patrząc na sedkawałek, widać, że szukał, alt": "a następnie czytał, aż znalazł ". Woops, najwyraźniej ... (Zastanawiam się, ile z tych rozwiązań nie przejdzie testu jednostkowego e̲͕̲̪v̲̺̗̱̬er̶͎y̦ ͖̙̝̦s҉̟̜i͓͜n̡g̸l͎̠̹̪͈͉͚͟e̩͙̙̣̲͕͘ ̴͎͉̳̮a̢͕l̯̦̮̥̺̱̤t̕ ͕̮̪̙̬̲̪͘t̰͙̘̪̼ͅex̺͕͍͔̠̮ͅt̪͔̀ ?: P)
i336_
4

Python 2 , 115 106 bajtów

-8 bajtów dzięki ovs. -1 bajt dzięki Jonathan Allan.

Pomyślałem, że opublikuję tam standardową odpowiedź z biblioteki.

lambda n:[json.load(urllib.urlopen('http://xkcd.com/%d/info.0.json'%n))['alt']][n==859]
import urllib,json
całkowicie ludzki
źródło
1
lambda n:[json.load(urllib.urlopen('https://xkcd.com/%d/info.0.json'%n))['alt']][n==859]dla -8 bajtów.
ovs
1
Powinien działać ze http://zbyt oszczędnym bajtem.
Jonathan Allan
4

Bash + curl + jq: 73 66 bajtów

Najkrótsza odpowiedź, która nie korzysta z biblioteki specyficznej dla xkcd. jq jest narzędziem do manipulowania obiektami json w powłoce i jest do tego wyposażony w parsujący język.

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'

Rozszerzenie poniżej:

curl -Ls - Zapytanie, ale możesz przekierować (w tym przypadku na stronę https) i nie dawać niepowiązanych wyników.

xkcd.com/$1/info.0.json - Bezwstydnie skradziony z innej odpowiedzi.

|jq -r- Uruchom jqw trybie „surowego wyjścia” przy użyciu następującego polecenia.

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

Teraz skrypt został przerobiony do użycia, //co jest odpowiednikiem a or bw pythonie, i używamy a, |notaby każda prawdziwa wartość była uważana za fałszywą, aby druga //mogła wydrukować.alt

Aviator45003
źródło
2

JavaScript (ES6), 177 175 bajtów

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

Wkleić do konsoli przeglądarki, a następnie wykonać f(859)lub f(404)etc - te dwa powinny błąd w konsoli, mimo że nie jest zakodowana, inni wyświetlić.

Pierwszy post od jakiegoś czasu, przepraszam, jeśli nie do końca spełnia zasady ...!

James Thorpe
źródło
Użyj x=>zamiast (x)=>.
user75200
2

PHP, 160 bajtów

<? 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
źródło
Poczekaj ... to nie jest specyfikacja. Naprawianie ...
Kevin_Kinsey
Naprawiony. Musiałem jednak dodać około 50 bajtów ... :(
Kevin_Kinsey
1
możesz usunąć 7 znaków usuwając echo i przenosząc przypisanie $ c wewnątrz
substratu
1
@BetaDecay, ponieważ nie sprawdzenie numeru wejściowego daje dodatkowe punkty
Einacio
1
@BetaDecay dobrze, skrypt, który zależy od treści, wygląda na źle napisany do mnie. Każdy inny tytuł zaczynający się w ten sposób złamałby go. Kevin_Kinsey możesz zastąpić ENT_QUOTES jego wartością = 3
Einacio
1

Perl, 129 167 bajtów

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

EDYCJA: Psyche to faktycznie

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

Zaimportuj dekodowanie HTML i dostęp do HTTP, a następnie wydrukuj grupę pasującą do (...) w

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

(trochę oszczędzając, pomijając {{Title zapytanie)

Za 404 i 859 śmierć.

archaephyrryx
źródło
Co rozumiesz przez „prawidłowo obsługuje 859”?
Beta Decay
@BetaDecay Drukuje rzeczywisty tekst
alternatywny
1
the program must throw an error when given the numbers 859 or 404
Beta Decay
Co to jest zdefiniowane jako „wyrzucić błąd”?
archaephyrryx
Nvm diejest wystarczająco krótki
archaephyrryx
1

BASH, 111 108 bajtów

a = $ (cat) curl -s https://xkcd.com/ $ a / | grep -oP '(? <= Tekst tytułu:) ([^}}] *)' [$ a = 404] && echo „Nie znaleziono $”

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


Aby uruchomić:
zmień # na liczbę komiksów. Uruchom z wiersza poleceń.

Dzięki @Ale za sugestię!

Silentziler
źródło
Po co czytać ze standardowego wejścia za pomocą cat zamiast po prostu 1 $ z wiersza poleceń? Zaoszczędziłoby to trochę bajtów ...
Ale
1

JavaScript (ES6), 118 96 94 bajty

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

Możesz wkleić to w konsoli przeglądarki i uruchomić f(123). Ale zrób to na stronie, która jest już na xkcd.com, w przeciwnym razie zobaczysz błąd CORS.

W przypadku 404 nie działa z:

Nieprzechwycony (w obietnicy) Składnia Błąd: Nieoczekiwany token <w JSON na pozycji 0

W przypadku 859 nie działa z:

Nieprzechwycony (w obietnicy) Składnia Błąd: brak) po liście argumentów

Aktualizacja: ostatnia wersja poprawnie sprawdza tekst alternatywny zamiast sprawdzania tylko 859 i goli kolejne 2 bajty.

Christiaan Westerbeek
źródło
Niestety nie udaje się to w przypadku dowolnego tekstu tytułowego zawierającego apostrof (np. 1084).
ETHprodukcje