Visualizza un xkcd


36

xkcd è il webcomic preferito da tutti e scriverai un programma che porterà un po 'più di umorismo a tutti noi.
Il tuo obiettivo in questa sfida è quello di scrivere un programma che prenderà un numero come input e visualizzi quel xkcd e il suo testo del titolo (testo del mouse).

Ingresso

Il tuo programma prenderà un intero positivo come input (non necessariamente uno per il quale esiste un fumetto valido) e visualizzerà tale xkcd: ad esempio, un input di 1500 dovrebbe visualizzare il fumetto "Upside-Down Map" su xkcd.com/1500, e quindi stampare il testo del titolo sulla console o visualizzarlo con l'immagine.

A causa della loro vicinanza attraverso il canale, c'è stata a lungo una tensione tra la Corea del Nord e il Regno Unito di Gran Bretagna e Irlanda del Sud. 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.

Caso di prova 2, per n = 859:

A parte i cervelli, mi chiedo quanti script di analisi di xkcd.com scritti male verranno interrotti su questo titolo (o ;; "'' {<< ['questo testo di passaggio del mouse."

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

Il tuo programma dovrebbe anche essere in grado di funzionare senza alcun input ed eseguire la stessa attività per l'ultimo xkcd trovato su xkcd.com e dovrebbe sempre mostrare quello più recente anche quando ne esce uno nuovo.

Non è necessario ottenere l'immagine direttamente da xkcd.com, è possibile utilizzare un altro database purché sia ​​aggiornato ed esistesse già prima che questa sfida si sollevasse. Non sono consentiti abbreviazioni di URL, ovvero URL che non hanno altro scopo che il reindirizzamento da qualche altra parte.

È possibile visualizzare l'immagine come desiderato, anche in un browser. Tuttavia, non è possibile visualizzare direttamente parte di un'altra pagina in un iframe o simile. CHIARIMENTO: non è possibile aprire una pagina Web preesistente, se si desidera utilizzare il browser è necessario creare una nuova pagina . È inoltre necessario visualizzare effettivamente un'immagine: non è consentito produrre un file di immagine.

Puoi gestire il caso in cui non ci sia un'immagine per un particolare fumetto (ad esempio, è interattivo o al programma è stato passato un numero maggiore della quantità di fumetti che sono stati rilasciati) in qualsiasi modo ragionevole desideri, incluso il lancio di un'eccezione o stampare una stringa di almeno un carattere, purché ciò significhi in qualche modo per l'utente che non esiste un'immagine per quell'input.

Puoi solo visualizzare un'immagine e generare il suo titolo-testo, oppure emettere un messaggio di errore per un fumetto non valido. Altro output non è consentito.

Questa è una sfida di , quindi vince il minor numero di byte.


1
@LukeFarritor Puoi solo visualizzare l'immagine e generare il testo del titolo o generare una forma di messaggio di errore per un fumetto non valido.
Pavel,

9
Se la dimensione del campione è 1, import antigravityin Python;)
Wayne Werner,

15
Divertente infatti n=404 xkcd.com/404 è una pagina 404.
Magic Octopus Urn,

11
xkcd is everyone's favorite webcomic [Citazione necessaria ]
Sanchises

11
Caso di prova: 859
betseg,

Risposte:


13

Perl + curl + feh, 86 84 75 byte

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

Richiede l' -pinterruttore. Ho tenuto conto di questo nel conteggio dei byte.


@Matt Ha funzionato su tutti i fumetti che ho provato. Corrisponde solo alle immagini con alt-text così.
uno spaghetto il

Potresti non aver bisogno delle virgolette attorno all'attributo src.
Conor O'Brien,

Non penso che ti serva ?nel primo gruppo di partite. È possibile utilizzare -pe $_=$2invece di print$2, ma il testo del titolo viene stampato solo dopo la chiusura di feh. Non sono sicuro che sia valido.
m-chrzan,

@ m-chrzan Sì, sembra che posso rilasciare il quantificatore riluttante lì, grazie. Ho pensato di usare -pma non ero sicuro di come si sarebbe sentito l'OP.
uno spaghetto il

@ ConorO'Brien Purtroppo Randall osserva buone pratiche di codifica HTML ... e catturare le virgolette non cita quindi gli argomenti a causa del funzionamento dei backtick in Perl.
uno spaghetto il

9

PowerShell v3 + 110 99 107 103 byte

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

Grazie a Timmy per aver contribuito a salvare alcuni byte utilizzando le assegnazioni in linea.

Se non viene passato alcun argomento, allora $argsè nullo e otterrà solo il fumetto corrente. Scarica l'immagine, abbinando quella con il testo alternativo, in un file nella directory corrente dello script corrente. Quindi visualizzalo con il visualizzatore predefinito di jpg. Il testo alternativo viene quindi visualizzato sulla console. iwrè un alias perInvoke-WebRequest

Se il numero passato (o qualsiasi input non valido per quella materia) non corrisponde al processo fallisce con almeno un errore 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.

Ho appena ricevuto il mio privilegio di commento su questo sub ora, controlla la mia risposta molto simile
colsw

@ConnorLSW Bel approccio nella tua risposta. Cose a cui pensare per la prossima volta.
Matt,

8

AutoIt , 440 byte

Sì, è lungo, ma è stabile.

#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

Prima di tutto, questo non usa RegEx per raschiare il sito (perché non ho tempo per testarlo su tutti i fumetti), ma piuttosto usa l'API di Internet Explorer per scorrere i imgtag del DOM fino a quando non ne trova uno con il testo del titolo.

Il flusso binario viene letto dall'URL dell'immagine e reso in una bitmap usando GDIPlus. Questo viene quindi visualizzato in una bella interfaccia grafica di dimensioni automatiche con una descrizione comandi reale per farlo comportare quasi esattamente come il sito Web.

Ecco un test case ( _(859)):

)


4
Sarebbe meglio se si aggiungesse nuovamente la parentesi nell'immagine.
Matt,

Wow, ho appena scoperto che posso eseguire AutoIt sotto Wine su Ubuntu. Ora tutto quello che devo fare è far funzionare IE lì.
Ripensandoci

2
@ElPedro Se hai una CPU moderna, usa qemu KVM e seamlessRDP (fondamentalmente un parallelo fai-da-te per Linux) invece di wine. Questo integra perfettamente le app di Windows nel desktop di Linux e ha compatibilità al 100% + passthrough GPU. Solo un consiglio
mınxomaτ,

Grazie @ mınxomaτ. Potrei provarlo. Lavoro con Windows tutto il giorno, quindi preferisco usare Linux (varie versioni) senza lavoro, ma sono sempre interessato a sperimentare :) Suggerimento ricevuto con gratitudine.
ElPedro,

7

Powershell, 93 byte

93 Versione byte per utilizzare il visualizzatore di immagini locale.

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

Ho salvato 2 byte rimuovendo le doppie virgolette inutili, quindi un altro lotto usando ("http:"+$n.src)invece di "https://"+$n.src.trim("/")- poiché imgsrc è //già presente su di esso e xkcd non richiede 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("/"))

estremamente simile alla risposta PowerShell di Matts, (probabilmente dovrebbe essere un commento ma bassa reputazione)

Invece questo apre una nuova scheda / finestra nel browser predefinito e altre cose, salvando alcuni byte.

iwr è un alias per Invoke-WebRequest

sapsè un alias per il Start-Processquale si apre 'esso' nel contesto predefinito.


Aggirando i limiti delle regole sull'apertura di una pagina Web esistente, perché si tratta solo di avviare direttamente il browser sul file .jpg (o qualsiasi altra cosa) preesistente, ma una bella risposta.
AdmBorkBork,

@TimmyD potrebbe avere frainteso qui allora - ho pensato è possibile utilizzare la pagina web xkcd in sé - si può solo cambiare sapsper iwre aggiungere `x.jpg -OutF;. Ii x *` alla fine se si vuole per aprire nel locale predefinito visualizzatore di immagini.
Colsw,

1
L'OP ha specificato che non è consentito aprire una pagina Web preesistente. Penso che la versione a 93 byte sia a posto
uno spaghetto il

Non penso che funzionerà sempre allo stesso modo se dai un numero che funziona e un numero che non funziona. Si aprirà l'immagine che esisteva dalla corsa precedente.
Matt,

Accetto la versione da 93 byte, ma la tua più breve viola le condizioni del puzzle.
Pavel

4

R, 358 328 310 298 byte

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

Con nuove righe e commenti:

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
}

Schermate dei casi di test:

per x = 1500: per x = 1500 (png)

per x vuoto:
per x = ''

caso quando l'immagine è un jpeg:
per x = 10 (jpeg)

x = 859:
x = 859


Mi chiedo se è necessario visualizzare l'immagine nelle dimensioni corrette. Quando stavo giocando con questa sfida, l'ho fatto semplicemente plot.new();rasterImage(...).
Billywob,

@Billywob Beh, sarebbe completamente distorto in quanto la dimensione predefinita per la trama è 7x7 pollici. È vero che l'OP non ha chiesto esplicitamente che l'immagine non fosse distorta, ma la preferisco in questo modo :) Sto comunque considerando la possibilità di sbarazzarmi di xaxse yaxspoiché il risultato sarebbe comunque proporzionato.
plannapus,


2

Python 2.7, 309 299 295 274 byte

Programma completo. Sicuramente più giocabile a golf, ma avendo letto i fumetti di xkcd per così tanto tempo non potevo lasciarlo passare (chissà se questo sarà utile in futuro per navigare facilmente in xkcd).

Se non viene passato alcun input, viene visualizzato il fumetto corrente. Se un numero di fumetti valido viene passato come input, ottiene quel fumetto. Se viene passato un input non valido (non un numero comico nell'intervallo valido), viene generato un errore.

Eventuali suggerimenti su come ridurre il numero di byte sono benvenuti! Tornerò (e aggiungerò spiegazione) quando avrò più tempo.

-10 byte grazie a @Dopapp

-21 byte grazie a @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
È possibile modificare try:...e except:...su try:n=...e except:n='', risparmiando 10 byte in totale
Daniel,

1
Perché hai anche una trydichiarazione? Le specifiche del programma indicano che otterrai sempre un numero intero positivo.
Kade,

@Shebang dovrebbe anche restituire l'ultimo fumetto quando non c'è input. Non sono stato in grado di gestire questo caso senza intaccare l'eccezione dell'errore di input.
Ioannes,

1
@Joannes Perché non usarlo raw_input()? Per impostazione predefinita, l'utente può premere [Enter]e nconterrà comunque la stringa vuota. Se rimuovi quel blocco try-tranne e t=u.urlopen(h+x+n).read() -> t=u.urlopen(h+x+raw_input()).read()lo ottieni fino a 274 byte.
Kade,

Questo non funziona più, perché utilizzano gli URL di immagini xkcd https. Tuttavia, è ancora valido, perché ha funzionato al momento della pubblicazione. Per farlo funzionare ora, cambia la riga 3 per iniziare con h='https://'+1 byte.
Mego

2

PHP, 42 byte

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

Salvare in un file e accenderlo nel server Web preferito


1
Benvenuti in PPCG! Non conosco PHP, ma non sembra esserci una parte del tuo codice che recuperi il testo del titolo dell'immagine?
Pavel,

1

JavaScript + HTML, 124 + 18 = 142 byte

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>

Soluzione di origine incrociata grazie alla risposta di Kaiido qui .

17 byte ( //crossorigin.me/) possono essere salvati se il proxy richiesto per connettersi a xkcd.com può essere sottratto ( meta post su questo ).

Test dello 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 + Richieste + PIL, 192 186 byte

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"])

Apre un visualizzatore di immagini (qualunque sia l'impostazione predefinita sul sistema su cui è in esecuzione) contenente il fumetto e pubblica il testo del titolo sulla console.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.