Насколько облачно это?


22

Вызов

Учитывая изображение неба, вы должны вывести облачность в октах. Предоставленное изображение будет файлом изображения (тип зависит от вас), а вывод должен быть в состоянии STDOUT.

окты

В метеорологии окта - это единица измерения, используемая для описания количества облачного покрова в любом данном месте, например на метеостанции. Небесные условия оцениваются исходя из того, сколько восьмых неба покрыто облаками, в пределах от 0 окт (полностью чистое небо) до 8 окт (полностью пасмурно).

Небо всегда будет изображением примерно с полудня (таким образом, голубое небо, а не красное / ночное небо).

Цвет облака всегда будет цветом, который соответствует следующей схеме:

#ABCDEF

Где AB >= C0, CD >= C0и EF >= C0.

Или в RGB:

(A, B, C)

Где A >= 192, B >= 192и C >= 192.

Вот процентные покрытия, связанные с октами:

0%    - 0 oktas
12.5% - 1 okta
25%   - 2 oktas
37.5% - 3 oktas
50%   - 4 oktas
62.5% - 5 oktas
75%   - 6 oktas
87.5% - 7 oktas
100%  - 8 oktas

Проценты - это процент изображения, которое является облачным.

Если у вас процентное облако вашего изображения не кратно 12,5, вам следует округлить до ближайшего.

Выход

Выход должен быть просто номером Okta (вы не должны произносить единицу измерения).

Примеры

1 окта (18.030743615677714% облаков)

0 окт (0.0% облачность)

3 окты (42.66319444444445% облаков)

1 окта (облако 12.000401814778645%)

Код Python, используемый для вычисления чисел

выигрыш

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


Разве не последние 3 окты?
TheLethalCoder

@TheLethalCoder Whoops, отредактировано
Beta Decay

Существует ли максимум размеров изображения?
Лохматый

2
Я добавил 4-й тест, который требует округления до 12,5, так как ответы, использующие целочисленные значения, прошли бы первые 3 теста.
Джастин Маринер,

1
О языках, которые не имеют возможностей обработки изображений, таких как C ++, можно ли использовать библиотеку? Если да, то для количества байтов он должен учитывать только написанный код или размер DLL-файлов, необходимых для запуска программы?
HatsuPointerKun

Ответы:


10

Python 2 , 114 110 98 байт

-4 байта благодаря TheLethalCoder
-12 байтов благодаря Рууду

import PIL.Image as P
i=P.open(input()).getdata()
print round(8.*sum(min(x)>191for x in i)/len(i))

Попробуйте онлайн!


Использовать 191вместо?
TheLethalCoder

2
Я собирался предложить x&y&z&192>191, но обновленная версия так же коротка.
Арно

2
Не могли бы вы потенциально заменить import PIL.Image as Pс from PIL.Image import*и сохранить 1 байт при изменении i=P.openв i=open? Я не знаю, может ли это вызвать проблемы, поскольку open - это уже определенная функция, но я не могу проверить, так как у меня нет возможности установить модуль.
Арнольд Палмер

1
Да, это похоже на работу. Сохраняет 1 байт.
Арфи

2
@Rod ваш код не должен работать на всех платформах - язык определяется интерпретатором. Если это работает для вас, то это действительно.
Тим

10

MATL , 18 17 байт

Yi191>3&A1eYm8*Yo

Пример запускается с четырьмя предоставленными изображениями (извините за качество предварительного просмотра; нажмите для получения полного разрешения):

введите описание изображения здесь

Или удалите последние четыре символа, чтобы увидеть результаты без округления:

введите описание изображения здесь

объяснение

Yi     % Implicitly input filename or URL. Read image. Gives an M×N×3 array
191>   % Does each entry exceed 191?
3&A    % True for 3rd-dim "lines" that only contain true. Gives an M×N matrix
1e     % Linearize (flatten) into a 1×L row vector, with L = M*N
Ym     % Mean of vector
8*     % Multiply by 8
Yo     % Round. Implicitly display

Интересно, что можно сделать с помощью esolangs
Евгений Новиков

6

Java (OpenJDK 8) , 204 байта

i->{int x=0,y=0,t=0,w=i.getWidth(),h=i.getHeight();for(;x<w;)for(y=0;y<h;){java.awt.Color c=new java.awt.Color(i.getRGB(x++,y++));if(c.getRed()>191&&c.getBlue()>191&&c.getGreen()>191)t++;}return 8*t/w/h;}

Попробуйте онлайн! Я всегда забываю, что TIO выводит STDERR на вкладку отладки. Может быть, он мог бы выделить красным цветом в случае ошибки?


Несколько вещей: ваш код в настоящее время выполняется в бесконечном цикле, так как вы никогда не увеличиваете xили y. Вы назначены y=0дважды, поэтому вы можете удалить первое назначение. Класс Colorдолжен быть либо полностью квалифицированным ( java.awt.Color), либо вы должны включить импорт в число байтов. И ваш код не выполняется для 4-го теста (возвращает 0 вместо 1).
Джастин Маринер,

Я знаю , что это было некоторое время, но вы можете играть в гольф 6 байт, удалив скобки внутрипартийной для цикла, и изменение &&в &и ,y=0в ,y: Попробуйте его в Интернете.
Кевин Круйссен

6

C #, 150 146 байт

b=>{int t=0,c=0,w=0,h;for(;w<b.Width;++w)for(h=0;h<b.Height;++t){var p=b.GetPixel(w,h++);if(p.R>191&p.G>191&p.B>191)c++;}return(int)(c/(t+0d)*8);}

Сохранено 4 байта благодаря @Ian H.

Полная / Отформатированная версия:

using System.Drawing;

namespace System
{
    class P
    {
        static void Main()
        {
            Func<Bitmap, int> f = b =>
            {
                int t = 0, c = 0, w = 0, h;
                for (; w < b.Width; ++w)
                    for (h = 0; h < b.Height; ++t)
                    {
                        var p = b.GetPixel(w, h++);

                        if (p.R > 191 & p.G > 191 & p.B > 191)
                            c++;
                    }

                return (int)(c / (t + 0d) * 8);
            };

            string[] testCases =
            {
                @"Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG",
                @"spanish-sky.jpeg",
                @"why-is-sky-blue-1.jpg",
            };

            foreach (string testCase in testCases)
            {
                using (Bitmap bitmap = new Bitmap(testCase))
                {
                    Console.WriteLine(f(bitmap));
                }
            }

            Console.ReadLine();
        }
    }
}

for(h=0 h<b.Height;++t)Я думаю, что вы пропустили
точку с запятой

2
Вы можете заменить /0.125с *8в конце , чтобы сэкономить несколько байт.
Ян Х.

@ Cowsquack Я бы удалил точку с запятой вместо пробела! Исправлено сейчас ..
TheLethalCoder

3

C #, 313 байтов

namespace System.Drawing.Imaging{b=>{unsafe{int t=0,c=0,y=0,x,w=b.Width,h=b.Height;var d=b.LockBits(new Rectangle(0,0,w,h),(ImageLockMode)1,(PixelFormat)137224);for(;y<h;++y){var r=(byte*)d.Scan0+y*d.Stride;for(x=0;x<w*3;++t)if(r[x++]>191&r[x++]>191&r[x++]>191)c++;}b.UnlockBits(d);return(int)(c/(t+0d)/0.125);}}}

Очевидно, дольше, чем мой другой ответ, но этот использует LockBitsи unsafeкод для прямого доступа к изображению в памяти; как таковой он невероятно быстр. Я мог бы, вероятно, удалить вызов, UnlockBitsно это более правильно там.

Полная / Отформатированная версия:

namespace System.Drawing.Imaging
{
    class P
    {
        static void Main()
        {
            Func<Bitmap, int> f = b =>
            {
                unsafe
                {
                    int t = 0, c = 0, y = 0, x, w = b.Width, h = b.Height;

                    var d = b.LockBits(new Rectangle(0, 0, w, h), (ImageLockMode)1, (PixelFormat)137224);
                    for (; y < h; ++y)
                    {
                        var r = (byte*)d.Scan0 + y * d.Stride;

                        for (x = 0; x < w * 3; ++t)
                            if (r[x++] > 191 & r[x++] > 191 & r[x++] > 191)
                                c++;
                    }
                    b.UnlockBits(d);

                    return (int)(c / (t + 0d) / 0.125);
                }
            };

            string[] testCases =
            {
                @"Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG",
                @"spanish-sky.jpeg",
                @"why-is-sky-blue-1.jpg",
            };

            foreach (string testCase in testCases)
            {
                using (Bitmap bitmap = new Bitmap(testCase))
                {
                    Console.WriteLine(f(bitmap));
                }
            }

            Console.ReadLine();
        }
    }
}

3

PowerShell , 200 байт

$a=New-Object System.Drawing.Bitmap $args[0]
0..($a.Height-1)|%{$h=$_;0..($a.Width-1)|%{$i+=(("$($a.GetPixel($_,$h)|select R,G,B)"|iex)['R','G','B']-ge192).count-eq3}}
[int]($i/($a.Height*$a.Width)*8)

Получает ввод $args[0]как полный путь к файлу изображения, создает New Bitmapобъект в $a. Это просто имя внутреннего объекта; поддерживает JPG, PNG и т. д.

Затем мы делаем двойной цикл по изображению, .heightа затем .widthпо изображению, касаясь каждого pixel. Мы извлекаем R,G,Bзначения и затем выбираем те из них, которые являются -greaterthanor equal, 192и проверяем , что countэто 3(то есть, все они являются белыми). Этот логический результат добавляется в наш аккумулятор $i.

Затем мы делим, чтобы получить процент, умножаем его 8на количество окт, а затем [int]получаем целочисленный результат. (Обратите внимание, что при этом выполняется округление Banker's - если это не разрешено, потребуется еще несколько байтов для изменения метода округления.)


2

постоянный ток, 74 байта

???*sa?[1+]ss[r1+r]st[?191<s]su0ddsd[0luxluxlux3=t1+dla>r]dsrxr8*la2/+la/p

Ввод принимается в виде файла p3 ppm со всеми пробелами в виде символов новой строки. Выход на STDOUT.

Попробуйте онлайн!


2

JavaScript, 83 77 байт

-6 байт по ETHproductions

f=i=>(z=a=b=0,i.map(e=>{z=e<192||z;(++b%4)||((z||(a+=64))&&(z=0))}),a/b+1>>1)

входные

Фото № 1

Фото № 2

Фото № 3

Фото № 4

демонстрация


1
Очень хорошее решение. Удобный трюк с функциями стрелок ES6 - заключать все в круглые скобки, разделяя их запятыми ( a=>(b,c,d)) вместо выполнения a=>{b;c;return d}или a=>eval("b;c;d"). Это работает, если у вас нет какого-либо цикла, и в этом случае вам, вероятно, лучше всего использовать этот evalметод.
ETHproductions

2

C (POSIX), 103 байта

Предполагается ввод в виде файла BMP на стандартный ввод.

b,c,i,m=0xc0c0c0;main(){lseek(0,54,0);for(;read(0,&b,3);c+=(b&m)==m,i++);printf("%d",(i+16*c)/(2*i));}

2

Машинный код x86, 34 байта

51
31 D2
AD
F7 D0
25 C0 C0 C0 00
75 01
42
E2 F3
C1 E2 03
DB 04 24
52
DB 04 24
DE F1
DB 1C 24
58
5A
C3

Эти байты кода определяют функцию, которая принимает битовый массив и возвращает целочисленное значение, указывающее его окты. Как и в C , массивы (например, растровые изображения) представлены в виде указателя на первый элемент и размера / длины. Таким образом, эта функция принимает два параметра: общее количество пикселей в растровом изображении (строки × столбцы) и указатель на само растровое изображение.

В этом коде используется пользовательское соглашение о вызовах на основе регистров, в котором указатель растрового изображения передается в ESIрегистр, а размер растрового изображения передается в ECXрегистр. Результат (окты), как обычно, возвращается в EAX.

Как уже говорилось выше, входные данные принимаются как растровые изображения. В частности, используется 32-битный формат в формате с прямым порядком байтов, но альфа-канал (байт высшего порядка) игнорируется. Это упрощает многие вещи, позволяя нам просто перебирать каждый пиксель и проверять его 32-битное значение цвета RGB. Умная оптимизация также используется здесь. Вместо того, чтобы выделять каждый компонент цвета и проверять, равен ли он> = 192, мы просто маскируем все 32-битное значение на 0xC0C0C0 и проверяем, равен ли результат> = 0xC0C0C0. Это будет иметь значение true для всех «облачных» цветов и false для всех «небесных» (не облачных) цветов. Ну, я думал , что это было умно! :-) Это, безусловно, экономит большое количество байтов.

Поэтому, чтобы протестировать этот код, вам нужно будет преобразовать входные изображения в растровые изображения 32 бит / бит. Вы не можете использовать Windows Paint для этого, потому что он поддерживает максимум 24 бит на пиксель. Тем не менее, есть ряд других программных решений, которые могут сделать это, например, Adobe Photoshop. Я использовал этот бесплатный инструмент , который конвертирует PNG в 32-битный BMP в Windows, что означает, что вам нужно конвертировать только из JPEG в PNG (что может сделать Paint).

Другие предположения, которые я высказываю, в высшей степени обоснованы:

  • Предполагается, что битовая карта имеет размер больше 0 ( то есть предполагается, что она содержит по меньшей мере один пиксель). Это разумно, потому что, когда у них нулевое небо, у нас больше проблем, чем в метеорологии.
  • Предполагается, что флаг направления ( DF) ясен, поэтому мы будем корректно выполнять итерацию по растровому изображению, используя LODSDинструкцию. Это то же предположение, которое принято большинством соглашений о вызовах x86, поэтому оно выглядит справедливым. Если вам это не нравится, добавьте 1 байт в счетчик для CLDинструкции.
  • Предполагается, что режим округления для FPU x87 установлен на округление до ближайшего четного. Это гарантирует, что мы получим правильное поведение, когда преобразуем количество окт из временного числа с плавающей запятой в конечный целочисленный результат, что подтверждается контрольным примером № 4. Это предположение разумно, потому что это состояние по умолчанию для FPU, и его необходимо поддерживать даже в коде C (где усечение является поведением округления по умолчанию, заставляя компиляторы, которые хотят быть совместимыми со стандартами, генерировать неэффективный код, который изменяет округление режим, выполняет преобразование, а затем изменяет режим округления обратно).

Неуправляемая сборка мнемоники:

; int ComputeOktas(void*    bmpBits  /* ESI */,
;                  uint32_t bmpSize  /* ECX */);
   push  ecx                  ; save size on stack
   xor   edx, edx             ; EDX = 0 (cloudy pixel counter)

CheckPixels:
   lodsd                      ; EAX = DS:[ESI]; ESI += 4
   not   eax
   and   eax, 0x00C0C0C0
   jnz   NotCloudy
   inc   edx
NotCloudy:
   loop  CheckPixels          ; ECX -= 1; loop if ECX > 0

   shl    edx, 3              ; counter *= 8
   fild   DWORD PTR [esp]     ; load original size from stack
   push   edx
   fild   DWORD PTR [esp]     ; load counter from stack
   fdivrp st(1), st(0)        ; ST(0) = counter*8 / size
   fistp  DWORD PTR [esp]     ; convert to integer, rounding to nearest even
   pop    eax                 ; load result
   pop    edx
   ret

Конечно, вы не сделали все это так, и все еще задаетесь вопросом, как работает код? :-)
Ну, это довольно просто. Мы просто перебираем растровое изображение по одному 32-битному значению за раз, проверяя, является ли значение пиксельного RGB «облачным» или «не облачным». Если облачно, мы увеличиваем наш предварительно обнуленный счетчик. В конце мы вычисляем: облачные пикселиобщее количество пикселей  × 8
(что эквивалентно: облачным пикселямобщее количество пикселей  ÷ 0,125).

Я не могу включить ссылку TIO для этого из-за необходимости ввода изображений. Однако я могу предоставить вам жгут, который я использовал для проверки этого в Windows:

#include <stdio.h>
#include <assert.h>
#include <Windows.h>

int main()
{
   // Load bitmap as a DIB section under Windows, ensuring device-neutrality
   // and providing us direct access to its bits.
   HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,
                                        TEXT("C:\\...\\test1.bmp"),
                                        IMAGE_BITMAP,
                                        0, 0,
                                        LR_LOADFROMFILE  | LR_CREATEDIBSECTION);
   assert(hBitmap != NULL);

   // Get the bitmap's bits and attributes.
   DIBSECTION dib;
   GetObject(hBitmap, sizeof(dib), &dib);
   assert(dib.dsBm.bmBitsPixel == 32);
   uint32_t cx = dib.dsBm.bmWidth;
   uint32_t cy = abs(dib.dsBm.bmHeight);
   uint32_t sz = cx * cy;
   assert(sz > 0);

   int oktas = ComputeOktas(sz, dib.dsBm.bmBits);

   printf("%d\n", oktas);

   return 0;
}

Будьте осторожны с этим, хотя! Как определено выше, ComputeOktasиспользуется пользовательское соглашение о вызовах, которое компилятор C не будет соблюдать. Вам необходимо добавить код вверху процедуры на языке ассемблера, чтобы загрузить значения из стека в ожидаемые регистры, например :

mov  ecx, DWORD PTR [bmpSize]
mov  esi, DWORD PTR [bmpBits]

1

JavaScript (ES6), 218 байт

(a,c=document.createElement`canvas`,w=c.width=a.width,h=c.height=a.height,x=c.getContext`2d`)=>x.drawImage(a,0,0)||x.getImageData(0,0,w,h).data.reduce((o,_,i,d)=>o+(i%4|d[i++]<192|d[i++]<192|d[i]<192?0:1),0)/w/h*8+.5|0

Принимает Imageобъект в качестве входных данных, который может быть создан из <image>элемента.

Проверьте это здесь на CodePen!

альтернатива

Если входные данные могут быть приняты как плоский массив значений RGBA с размерами: 82 байта

(d,w,h)=>d.reduce((o,_,i)=>o+(i%4|d[i++]<192|d[i++]<192|d[i]<192?0:1),0)/w/h*8+.5|0

Этот формат ввода очень похож на то, что предлагает этот ответ на мета .


1

Mathematica 89 байт

Далее бинаризируется изображение и определяется доля облаков, то есть белые пиксели. Затем он определяет, сколько раз .125 вписывается в результат. Возвращает пол этого значения.

o@i_:=⌊8Tr@Flatten[ImageData@MorphologicalBinarize[i,.932],1]/Times@@ImageDimensions@i⌋
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.