Відобразити xkcd


36

xkcd - улюблений веб-коміксом кожного, і ви будете писати програму, яка принесе трохи більше гумору для всіх нас.
Ваша мета в цьому виклику - написати програму, яка буде приймати число як введення та відображення цього xkcd та його заголовкового тексту (mousover text).

Вхідні дані

Ваша програма прийме позитивне ціле число як вхідне (не обов'язково таке, для якого існує дійсний комікс) і відобразить цей xkcd: наприклад, на вході 1500 повинно відображатися комічне "Перевернута карта" на xkcd.com/1500, а потім або надрукуйте його текст заголовка на консолі або покажіть його із зображенням.

Через їх близькість до каналу, між Північною Кореєю та Сполученим Королівством Великобританії та Південної Ірландії тривалий час виникає напруга. 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.

Тестовий випадок 2, при n = 859:

Замислюючись, мені цікаво, скільки погано написаних сценаріїв розбору xkcd.com будуть порушені під цим заголовком (або ;; "'' {<< ['цей текст миші".

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

Ваша програма також повинна мати можливість функціонувати без будь-якого введення та виконувати те саме завдання для самого останнього xkcd, знайденого на xkcd.com, і завжди має відображати найсвіжіший, навіть коли новий працює.

Вам не доведеться отримувати зображення безпосередньо з xkcd.com, ви можете використовувати іншу базу даних, поки вона є актуальною і вже існувала до того, як ця проблема піднімалася. Забороняються URL-адреси, тобто URL-адреси, без яких-небудь інших цілей, крім перенаправлення на інше місце, забороняються.

Ви можете відображати зображення будь-яким обраним вами способом, в тому числі в браузері. Однак ви не можете безпосередньо відображати частину іншої сторінки в iframe або подібній. ПОЯСНЕННЯ: ви не можете відкрити попередню веб-сторінку, якщо ви хочете скористатися браузером, вам доведеться створити нову сторінку . Ви також повинні фактично відображати зображення - виведення файлу зображення заборонено.

Ви можете вирішити випадок, коли немає зображення для певного коміксу (наприклад, це інтерактивна програма або передано програму на номер більше, ніж кількість випущених коміксів) будь-яким розумним способом, включаючи викидання виключення або роздрукувати принаймні односимвольний рядок, якщо це якимось чином означає користувачеві, що для цього вводу немає зображення.

Ви можете відображати лише зображення та виводити його текст заголовка або виводити повідомлення про помилку для недійсного коміксу. Інший вихід заборонений.

Це проблема з , тому виграє найменше байтів.


1
@LukeFarritor Ви можете лише відображати зображення та виводити текст заголовка або виводити певну форму повідомлення про помилку для недійсного коміксу.
Павло

9
Якщо розмір вашого зразка дорівнює 1, import antigravityв Python;)
Уейн Вернер

15
Кумедний факт n=404 xkcd.com/404 - це 404 сторінка.
Чарівна восьминога урна

11
xkcd is everyone's favorite webcomic [Цитування потрібно ]
Санчіз

11
Тестовий випадок: 859
betseg

Відповіді:


13

Perl + curl + feh, 86 84 75 байт

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

Потрібен -pперемикач. Я врахував це в кількості байтів.


@Matt Це працювало на всіх коміксах, які я спробував. Це відповідає лише зображенням з альт-текстом.
спагето

Можливо, вам не знадобляться цитати навколо атрибуту src.
Conor O'Brien

Я не думаю, що тобі потрібен ?перший у групі матчів. Можна використовувати -pі $_=$2замість print$2, але тоді текст заголовка друкується лише після закриття feh. Не впевнений, чи дійсно це.
m-chrzan

@ m-chrzan Так схоже, я можу скинути туди неохоче квантор, дякую. Я думав про використання, -pале не був впевнений, як буде почуватись з цього приводу.
спагетто

@ ConorO'Brien На жаль, Рендалл дотримується хороших методів кодування HTML ... і захоплення цитат не приводить аргументи через те, як працюють задні посилання в Perl.
спагето

9

PowerShell v3 + 110 99 107 103 байт

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

Дякую Тіммі за допомогу зберегти кілька байт за допомогою вбудованих завдань.

Якщо жодних аргументів не буде передано, $argsце недійсне значення, і воно просто отримає поточний комікс. Завантажте зображення, зіставивши зображення з текстом alt, у файл у поточному запущеному каталозі сценарію. Потім покажіть його за допомогою за замовчуванням переглядача jpg. Потім текст alt виводиться на консоль. iwrпсевдонім дляInvoke-WebRequest

Якщо передане число (або будь-який недійсний вхід для цього питання) не відповідає процесу, відбувається не менше 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.

Лише щойно я отримав мою привілей на коментар щодо цього підрозділу, ознайомтеся з моєю дуже подібною відповіддю
colsw

@ConnorLSW Гарний підхід у вашій відповіді. Про що варто подумати наступного разу.
Метт

8

AutoIt , 440 байт

Так, це довго, але стабільно.

#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

Перш за все, це не використовує RegEx для скребкування сайту (тому що я не маю часу тестувати це на всіх коміксах), а скоріше використовує API Internet Explorer, щоб перебирати imgтеги DOM, поки не знайде його з текстом заголовка.

Двійковий потік зчитується з URL-адреси зображення та передається в растрову карту за допомогою GDIPlus. Потім він відображається у приємному графічному інтерфейсі з автоматичним розміром із фактичною підказкою, щоб змусити його працювати майже так само, як веб-сайт.

Ось тестовий випадок ( _(859)):

)


4
Було б краще, якщо ви додали дужку назад у зображення.
Метт

Вау, щойно я дізнався, що я можу запустити AutoIt під Wine на Ubuntu. Тепер все, що мені потрібно зробити - це IE працювати над цим. Щодо другої думки ... +1 для відповіді
ElPedro

2
@ElPedro Якщо у вас є сучасний процесор, використовуйте замість вина qemu KVM та brezRR (в основному це паралелі DIY для Linux). Це безперешкодно інтегрує додатки Windows у робочий стіл Linux та має 100% сумісність + прохідність GPU. Просто порада.
mınxomaτ

Дякую @ mınxomaτ. Я можу це спробувати. Я працюю з Windows цілий день, тому вважаю за краще використовувати Linux (різні аромати) без роботи, але мені завжди цікаво експериментувати :) Підказка вдячна.
ElPedro

7

Powershell, 93 байт

93-байтна версія для використання локального переглядача зображень.

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

Збережено 2 байти, видаливши непотрібні подвійні лапки, потім ще один лот, використовуючи ("http:"+$n.src)замість "https://"+$n.src.trim("/")- оскільки imgsrc поставляється з //уже на ньому, а xkcd не вимагає 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("/"))

надзвичайно схожий на відповідь Маттса, (мабуть, це буде коментар, але низька репутація)

Натомість це відкриває нову вкладку / вікно у веб-переглядачі за замовчуванням та інші речі, зберігаючи деякі байти.

iwr псевдонім для Invoke-WebRequest

sapsпсевдонім, Start-Processякий відкриває "це" в контексті за замовчуванням.


Перебираючи краї правил щодо відкриття існуючої веб-сторінки, оскільки це просто запуск браузера на попередньо існуючому .jpg (або будь-якому іншому), але приємна відповідь.
AdmBorkBork

@TimmyD , можливо, неправильно зрозумів ось тоді - я припустив , що ви можете використовувати сам XKCD веб - сторінку - ви можете просто змінити , sapsщоб iwrі Append `-OutF x.jpg ;. II х *` до кінця , якщо ви хочете , щоб відкрити в локальній замовчуванням переглядач зображень.
colsw

1
ОП вказала, що вам заборонено відкривати попередньо існуючу веб-сторінку. 93-байтна версія, я думаю, що це добре
спагето

Я не думаю, що це завжди працюватиме однаково, якщо ви дасте число, яке працює, то число, яке не відповідає. Це відкриє зображення, яке існувало з попереднього циклу.
Метт

Я приймаю 93-байтну версію, але ваша коротша версія порушує умови головоломки.
Павло

4

R, 358 328 310 298 байт

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

З новими рядками та коментарями:

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
}

Скріншоти тестових випадків:

для х = 1500: для х = 1500 (png)

для x порожнім:
для x = ''

випадок, коли зображення є jpeg:
для х = 10 (jpeg)

х = 859:
х = 859


Цікаво, чи потрібно відображати зображення у правильних розмірах. Коли я грав із цим викликом, я просто робив це plot.new();rasterImage(...).
Billywob

@Billywob Ну це було б повністю спотворено, оскільки розмір за замовчуванням для ділянки - 7x7 дюймів. Це правда, що ОП прямо не вимагала, щоб зображення не було спотворене, але я вважаю за краще таким чином :) Я, однак, розглядаю можливість позбутися, xaxsі yaxsрезультат все одно буде пропорційним.
планнапус


2

Python 2.7, 309 299 295 274 байт

Повна програма. Безумовно, більш гольфуючий, але читаючи комікси xkcd так довго, я не міг пропустити це (хто знає, чи це буде корисно в майбутньому для легкого перегляду xkcd).

Якщо не введено жодного вводу, отримується поточний комічний. Якщо дійсний комічний номер передається як вхідний, то він отримує цей комічний. Якщо передано недійсний вхід (не комічний номер у допустимому діапазоні), видається помилка.

Будь-які пропозиції щодо зменшення кількості байтів вітаються! Буду переглянути (і додати пояснення), коли у мене буде більше часу.

-10 байт завдяки @Dopapp

-21 байт завдяки @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
Ви можете змінити try:...і except:...до try:n=...і except:n='', заощадивши в цілому 10 байт
Даніель

1
Чому у вас навіть є tryзаява? Специфікація програми говорить, що ви завжди отримаєте додатне ціле число.
Каде

@Shebang також повинен повернути останні комікси, коли немає вводу. Я не зміг керувати цим випадком без кешування винятком помилки введення.
Іоанна

1
@Joannes Чому б не використовувати raw_input()? За замовчуванням користувач може будь-коли натиснути [Enter]і nмістити порожній рядок. Якщо ви вилучите цей блок, за винятком спроб, і t=u.urlopen(h+x+n).read() -> t=u.urlopen(h+x+raw_input()).read()ви зменшите його до 274 байт.
Каде

Це більше не працює, оскільки використовуються URL-адреси зображень xkcd https. Однак він все-таки дійсний, бо працював на момент публікації. Щоб він працював зараз, змініть рядок 3, щоб почати з h='https://'+1 байта.
Mego

2

PHP, 42 байти

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

Збережіть у файлі та запишіть його на свій веб-сервер за вибором


1
Ласкаво просимо до PPCG! Я не знаю PHP, але, здається, не є частина вашого коду, яка отримує текст заголовка зображення?
Павло

1

JavaScript + HTML, 124 + 18 = 142 байти

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>

Рішення хрестового походження завдяки відповіді Каїдо тут .

17 байт (//crossorigin.me/ ) можна зберегти, якщо проксі, необхідний для підключення до xkcd.com, можна відняти ( мета-повідомлення про це ).

Тест-фрагмент

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 + Запити + PIL, 192 186 байт

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

Відкриває програму перегляду зображень (що є типовою для системи, в якій вона працює), що містить комікс, і надсилає текст заголовка до консолі.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.