Wyświetl xkcd


36

xkcd to ulubiony komiks internetowy, a ty napiszesz program, który przyniesie nam nieco więcej humoru.
Twoim celem w tym wyzwaniu jest napisanie programu, który weźmie liczbę jako dane wejściowe i wyświetli ten xkcd i jego tytuł-tekst (tekst narzuty).

Wkład

Twój program weźmie na wejściu dodatnią liczbę całkowitą (niekoniecznie taką, dla której istnieje prawidłowy komiks) i wyświetli ten xkcd: na przykład wejście 1500 powinno wyświetlać komiks „Upside-Down Map” na stronie xkcd.com/1500, a następnie wydrukuj tekst tytułu na konsoli lub wyświetl go wraz z obrazem.

Ze względu na bliskość kanału, od dawna istnieje napięcie między Koreą Północną a Zjednoczonym Królestwem Wielkiej Brytanii i Irlandii Południowej. Due to their proximity across the channel, there's long been tension between North Korea and the United Kingdom of Great Britain and Southern Ireland.

Przypadek testowy 2, dla n = 859:

Odkładając na bok, zastanawiam się, ile źle napisanych skryptów parsujących xkcd.com złamie ten tytuł (lub ;; "" {<< ['ten tekst najechania kursorem myszy ").

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

Twój program powinien także być w stanie funkcjonować bez żadnych danych wejściowych i wykonywać to samo zadanie dla najnowszego xkcd znalezionego na xkcd.com, i zawsze powinien wyświetlać najnowszy, nawet gdy nowy idzie w górę.

Nie musisz pobierać obrazu bezpośrednio z witryny xkcd.com, możesz korzystać z innej bazy danych, o ile jest ona aktualna i istniała, zanim wyzwanie się zwiększyło. Skracanie adresów URL, czyli adresy URL bez celu innego niż przekierowanie do innej lokalizacji, są niedozwolone.

Możesz wyświetlać obraz w dowolny sposób, w tym w przeglądarce. Być może nie , jednak bezpośrednio wyświetlać część innej strony w iframe lub podobnym. WYJAŚNIENIE: nie możesz otworzyć istniejącej strony, jeśli chcesz korzystać z przeglądarki, musisz utworzyć nową stronę . Musisz także wyświetlić obraz - wysyłanie pliku obrazu jest niedozwolone.

Możesz obsłużyć przypadek, w którym nie ma obrazu dla konkretnego komiksu (np. Jest on interaktywny lub program został przekazany o liczbie większej niż liczba komiksów, które zostały wydane) w dowolny rozsądny sposób, w tym chcesz zgłosić wyjątek lub wydrukowanie co najmniej jednoznakowego ciągu znaków, o ile w jakiś sposób dla użytkownika oznacza, że ​​nie ma obrazu dla tego wejścia.

Możesz wyświetlić tylko obraz i wyprowadzić jego tekst tytułowy lub wysłać komunikat o błędzie dla nieprawidłowego komiksu. Inne dane wyjściowe są niedozwolone.

To wyzwanie dla , więc wygrywa najmniej bajtów.


1
@LukeFarritor Możesz wyświetlić tylko obraz i wyprowadzić tekst tytułu lub wysłać komunikat o błędzie dla nieprawidłowego komiksu.
Pavel

9
Jeśli twoja próbka ma wielkość 1, import antigravityw Pythonie;)
Wayne Werner

15
Zabawny fakt, że n=404 xkcd.com/404 to strona 404.
Magic Octopus Urn

11
xkcd is everyone's favorite webcomic [Potrzebne
źródło

11
Przypadek testowy: 859
betseg

Odpowiedzi:


13

Perl + curl + feh, 86 84 75 bajtów

`curl xkcd.com/$_/`=~/<img src="(.*)" title="(.*?)"/;$_=$2;`feh "http:$1"`

Wymaga -pprzełącznika. Uwzględniłem to w liczbie bajtów.


@Matt Działa na wszystkich komiksach, które wypróbowałem. Dopasowuje tylko obrazy z tekstem alternatywnym, więc.
spaghetto

Możesz nie potrzebować cudzysłowów wokół atrybutu src.
Conor O'Brien

Nie sądzę, że potrzebujesz ?pierwszej grupy meczowej. Możesz użyć -pi $_=$2zamiast print$2, ale tekst tytułu jest drukowany dopiero po zamknięciu feh. Nie jestem pewien, czy to jest poprawne.
m-chrzan

@ m-chrzan Tak, wygląda na to, że mogę upuścić tam niechętny kwantyfikator, dzięki. Myślałam o użyciu, -pale nie byłam pewna, jak OP by się z tym czuł.
spaghetto

@ ConorO'Brien Niestety Randall przestrzega dobrych praktyk kodowania HTML ... a przechwytywanie cudzysłowów nie cytuje argumentów ze względu na sposób działania odwrotności w Perlu.
spaghetto

9

PowerShell v3 + 110 99 107 103 bajtów

iwr($x=((iwr "xkcd.com/$args").images|?{$_.title})).src.Trim("/") -outf x.jpg;if($x){ii x.jpg;$x.title}

Dzięki Timmy za pomoc w oszczędzaniu niektórych bajtów za pomocą wbudowanych zadań.

Jeśli nie zostaną przekazane żadne argumenty, $argsjest ono puste i otrzyma tylko bieżący komiks. Pobierz obraz, dopasowując obraz z tekstem alternatywnym, do pliku w bieżącym katalogu roboczym skryptu. Następnie wyświetl go w domyślnej przeglądarce plików jpg. Tekst alternatywny jest następnie wyświetlany na konsoli. iwrjest pseudonimem dlaInvoke-WebRequest

Jeśli przekazana liczba (lub jakiekolwiek nieprawidłowe dane wejściowe w tej sprawie) nie są zgodne, proces kończy się niepowodzeniem z co najmniej błędem 404.

iwr(                                  # Request the comic image from XKCD
  $x=((iwr "xkcd.com/$args").images|  # Primary search to locate either the current image
                                      # or one matching an argument passed
     ?{$_.title}))                    # Find the image with alt text
        .src.Trim("/")                # Using the images associated link and strip the leading slashes
  -outf x.jpg                         # Output the image to the directory local to where the script was run
if($x){                               # Test if the image acquisition was successful
    ii x.jpg                          # Open the picture in with the default jpg viewer
    $x.title                          # Display alt text to console
}                                     # I'm a closing bracket.

Właśnie dostałem teraz moje uprawnienia do komentowania tego subwoofera, sprawdź moją bardzo podobną odpowiedź
colsw

@ConnorLSW Ładne podejście w twojej odpowiedzi. Rzeczy do przemyślenia na następny raz.
Matt

8

AutoIt , 440 bajtów

Tak, jest długi, ale stabilny.

#include<IE.au3>
#include<GDIPlus.au3>
Func _($0='')
_GDIPlus_Startup()
$1=_IECreate('xkcd.com/'&$0)
For $3 In $1.document.images
ExitLoop $3.title<>''
Next
$4=_GDIPlus_BitmapCreateFromMemory(InetRead($3.src),1)
$6=_GDIPlus_ImageGetDimension(_GDIPlus_BitmapCreateFromHBITMAP($4))
GUICreate(ToolTip($3.title),$6[0],$6[1])
GUICtrlSendMsg(GUICtrlCreatePic('',0,0,$6[0],$6[1]),370,0,$4)
_IEQuit($1)
GUISetState()
Do
Until GUIGetMsg()=-3
EndFunc

Przede wszystkim nie używa RegEx do zeskrobywania strony (ponieważ nie mam czasu na testowanie tego na wszystkich komiksach), ale raczej używa API Internet Explorera do iteracji po imgtagach DOM, aż znajdzie tekst z tytułem.

Strumień binarny jest odczytywany z adresu URL obrazu i renderowany do bitmapy za pomocą GDIPlus. Jest to następnie wyświetlane w ładnym, automatycznym interfejsie graficznym z rzeczywistym podpowiedzią, dzięki czemu zachowuje się prawie dokładnie tak, jak strona internetowa.

Oto przypadek testowy ( _(859)):

)


4
Byłoby lepiej, jeśli ponownie dodasz wspornik do obrazu.
Matt

Wow, właśnie dowiedziałem się, że mogę uruchomić AutoIt w Wine na Ubuntu. Teraz wszystko, co muszę zrobić, to uruchomić IE. Po
namyśle

2
@ElPedro Jeśli masz nowoczesny procesor, zamiast wina użyj qemu KVM i seamlessRDP (w zasadzie zrób to sam dla Linuxa). Bezproblemowo integruje aplikacje Windows z pulpitem Linux i ma 100% kompatybilności + przejście przez GPU. Tylko wskazówka.
mınxomaτ

Dzięki @ mınxomaτ. Mogę spróbować. Pracuję z Windows przez cały dzień, więc wolę korzystać z Linuksa (różne smaki) poza pracą, ale zawsze jestem zainteresowany eksperymentowaniem :) Wskazówka z wdzięcznością.
ElPedro

7

PowerShell, 93 bajty

93 bajtowa wersja do używania lokalnej przeglądarki zdjęć.

$n=(iwr xkcd.com/$args).images|?{$_.title};$n.title;iwr ("http:"+$n.src) -OutF x.jpg;ii x.*

Zaoszczędzono 2 bajty, usuwając niepotrzebne podwójne cudzysłowy, a następnie wykorzystano inną partię ("http:"+$n.src)zamiast "https://"+$n.src.trim("/")- ponieważ imgsrc jest //już w nim dostępny, a xkcd nie wymaga https.

$n=(iwr xkcd.com/$args).images|?{$_.title};$n.title;saps ("http:"+$n.src)

$n=(iwr "xkcd.com/$args").images|?{$_.title};$n.title;saps ("https://"+$n.src.trim("/"))

bardzo podobny do odpowiedzi PowerSta Mattsa (prawdopodobnie powinien to być komentarz, ale niska reputacja)

Zamiast tego otwiera nową kartę / okno w domyślnej przeglądarce i inne rzeczy, oszczędzając niektóre bajty.

iwr jest pseudonimem dla Invoke-WebRequest

sapsjest aliasem, dla Start-Processktórego otwiera się „to” w domyślnym kontekście.


Ominięcie granic zasad otwierania istniejącej strony internetowej, ponieważ jest to po prostu bezpośrednie uruchomienie przeglądarki na wcześniej istniejącym pliku .jpg (lub cokolwiek innego), ale fajna odpowiedź.
AdmBorkBork

@TimmyD może nie zrozumiałeś o czym - Sądziłem, można użyć strony internetowej xkcd sam - można po prostu zmienić sapssię iwri dołączyć `-OutF x.jpg; ii. X *` do końca, jeśli chcesz go otworzyć w domyślnej lokalnej przeglądarka obrazów.
colsw

1
OP określił, że nie wolno otwierać wcześniej istniejącej strony internetowej. Wydaje mi się, że 93-bajtowa wersja jest w porządku
spaghetto

Nie sądzę, że to zawsze będzie działać tak samo, jeśli podasz liczbę, która działa, a następnie liczbę, która nie działa. Otworzy obraz, który istniał z poprzedniego uruchomienia.
Matt

Akceptuję 93-bajtową wersję, ale twoja krótsza narusza warunki układanki.
Pavel

4

R, 358 328 310 298 bajtów

f=function(x){H="http:";p=paste0;library(XML);a=xpathSApply(htmlParse(p(H,'//xkcd.com/',x)),'//div/img',xmlAttrs)[[1]];download.file(p(H,a[1]),'a');I=`if`(grepl('png',a[1]),png::readPNG,jpeg::readJPEG)('a');d=dim(I)/100;quartz(,d[2],d[1]);par(mar=rep(0,4));frame();rasterImage(I,0,0,1,1);cat(a[2])}

Dzięki nowym wierszom i komentarzom:

f=function(x){
H="http:"
p=paste0
library(XML) #Needed for xpathSApply, htmlParse and xmlAttrs
# The following line find the first img element and extract its attributes
a=xpathSApply(htmlParse(p(H,'//xkcd.com/',x)),'//div/img',xmlAttrs)[[1]]
download.file(p(H,a[1]),'a') #Download to a file called 'a'
I=`if`(grepl('png',a[1]),png::readPNG,jpeg::readJPEG)('a') #Check if png or jpeg and load the file accordingly
d=dim(I)/100 #convert dimension from pixel to inches (100 ppi).
quartz(,d[2],d[1]) #open a window of the correct dimension
par(mar=rep(0,4)) #Get rid of margins
frame() #Create empty plot
rasterImage(I,0,0,1,1) #Add png/jpeg to the plot
cat(a[2]) #Print title text to stdout
}

Zrzuty ekranu przypadków testowych:

dla x = 1500: dla x = 1500 (png)

dla x pusta:
dla x = ''

przypadek, gdy obraz jest JPEG
dla x = 10 (jpeg)

x = 859:
x = 859


Zastanawiam się, czy konieczne jest wyświetlenie obrazu we właściwych wymiarach. Kiedy bawiłem się tym wyzwaniem, po prostu to zrobiłem plot.new();rasterImage(...).
Billywob,

@Billywob Cóż, byłoby to całkowicie zniekształcone, ponieważ domyślny rozmiar fabuły to 7 x 7 cali. To prawda, że ​​OP nie zażądał wyraźnie, aby obraz nie był zniekształcony, ale wolę to w ten sposób :) Zastanawiam się jednak, czy się go pozbyć, xaxsa yaxswynik byłby nadal proporcjonalny.
plannapus


2

Python 2.7, 309 299 295 274 bajtów

Pełny program Zdecydowanie bardziej golfowy, ale po tak długim czytaniu komiksów xkcd nie mogłem tego przepuścić (kto wie, czy będzie to pomocne w przyszłości dla łatwego przeglądania xkcd).

Jeśli żadne dane nie zostaną przekazane, otrzyma bieżący komiks Jeśli poprawny numer komiksu zostanie przekazany jako dane wejściowe, wówczas otrzyma ten komiks. Jeśli przekazane zostanie niepoprawne wejście (nie numeryczny komiks w prawidłowym zakresie), zgłasza błąd.

Wszelkie sugestie dotyczące zmniejszenia liczby bajtów są mile widziane! Wrócę (i dodam wyjaśnienie), gdy będę miał więcej czasu.

-10 bajtów dzięki @Dopapp

-21 bajtów dzięki @Shebang

import urllib as u,re
from PIL import Image
h='http://';x='xkcd.com/'
o=u.URLopener()
t=u.urlopen(h+x+raw_input()).read()
c=sum([re.findall(r,t)for r in[h+'imgs.'+x+'c.*s/.*\.\w{1,3}','\.\w{1,3}" t.*e="(.*)" a']],[])
Image.open(o.retrieve(c[0],'1.png')[0]).show();print c[1]

1
Możesz zmienić try:...i except:...do try:n=...oraz except:n='', oszczędzając ci łącznie 10 bajtów
Daniel

1
Dlaczego w ogóle masz tryoświadczenie? Specyfikacja programu mówi, że zawsze otrzymasz dodatnią liczbę całkowitą.
Kade

@ Shebang powinien również zwrócić najnowszy komiks, gdy nie ma żadnych danych wejściowych. Nie byłem w stanie poradzić sobie z tą sprawą bez wykreślenia wyjątku błędu wejściowego.
Ioannes,

1
@Joannes Dlaczego nie skorzystać raw_input()? Domyślnie użytkownik może nacisnąć [Enter]i i tak nbędzie zawierać pusty ciąg. Jeśli usuniesz blok try-try i t=u.urlopen(h+x+n).read() -> t=u.urlopen(h+x+raw_input()).read()zejdziesz do 274 bajtów.
Kade

To już nie działa, ponieważ używają adresów URL obrazów xkcd https. Jest jednak nadal aktualny, ponieważ działał w momencie publikacji. Aby to działało teraz, zmień wiersz 3 na początek h='https://'na bajt +1.
Mego

2

PHP, 42 bajty

<?=@file('http://xkcd.com/'.$_GET[i])[59];

Zapisz do pliku i uruchom go na wybranym serwerze internetowym


1
Witamy w PPCG! Nie znam PHP, ale wydaje się, że nie ma części twojego kodu, która pobiera tekst tytułowy obrazu?
Pavel

1

JavaScript + HTML, 124 + 18 = 142 bajty

i=>fetch(`//crossorigin.me/http://xkcd.com/${i||""}/info.0.json`).then(r=>r.json()).then(d=>(A.innerHTML=d.alt,B.src=d.img))
<img id=B><p id=A>

Rozwiązanie krzyżowe dzięki odpowiedzi Kaiido tutaj .

17 bajtów (//crossorigin.me/ ) można zapisać, jeśli można odjąć proxy wymagane do połączenia z xkcd.com ( meta post na ten temat ).

Test Snippet

f=
i=>fetch(`//crossorigin.me/http://xkcd.com/${i||""}/info.0.json`).then(r=>r.json()).then(d=>(A.innerHTML=d.alt,B.src=d.img))
<style>img{width:50%}</style><input id=I> <button onclick="f(I.value)">Run</button><br>
<img id=B><p id=A>


1

Python 3 + żądania + PIL, 192 186 bajtów

from requests import*
import PIL.Image as f
from io import*
r=get("https://xkcd.com/%s/info.0.json"%input()).json()
f.open(BytesIO(get(r["img"],stream=1).content)).show()
print(r["alt"])

Otwiera przeglądarkę obrazów (zależnie od tego, która z nich jest domyślna w systemie, na którym jest uruchomiona), zawierającą komiks, i publikuje tekst tytułu na konsoli.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.