Наскільки хмарно?


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, вам слід округнути до найближчого.

Вихідні дані

Вихід повинен бути просто числом окта (вам не потрібно говорити одиницю).

Приклади

1 окта (18.030743615677714% хмара)

0 октав (0,0% хмара)

3 окти (42,66319444444445% хмара)

1 окта (12.000401814778645 хмара)

Код Python, який використовується для обчислення чисел

Перемога

Виграє найкоротший код у байтах.


Чи не останній 3 окта?
TheLethalCoder

@TheLethalCoder Whoops, відредаговано
Beta Decay

Чи є максимум розмірів зображення?
Shaggy

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? Я не знаю, чи це призведе до проблем, оскільки відкриття - це вже визначена функція, але я не можу перевірити, оскільки не маю можливості встановити модуль.
Арнольд Палмер

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значення, а потім вибираємо ті, які -gпереважають eякості 192та переконуємось, що countце 3(тобто всі вони є білими). Цей булевий результат додається до нашого акумулятора $i.

Потім ми ділимо їх, щоб отримати відсоток, помножимо на це, 8щоб отримати кількість октів, а потім [int]отримати просто цілий вихід. (Зауважте, що це виконує Округлення Банкіра - якщо це не дозволено, для зміни методу округлення буде ще кілька байтів.)


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-файлу на stdin.

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-bpp у форматі мало-ендіанського типу, але альфа-канал (байт найвищого порядку) ігнорується. Це спрощує багато речей, дозволяючи нам просто повторити кожен піксель і перевірити його 32-бітове значення RGB кольору. Тут також використовується розумна оптимізація. Замість того, щоб виділяти кожну кольорову складову та перевіряти, чи є вона> = 192, ми просто маскуємо все 32-бітове значення на 0xC0C0C0 і перевіряємо, чи результат>> 0xC0C0C0. Це оцінить як істинне для всіх "хмарних" кольорів, а неправдиве - для всіх "небесних" (нехмарних) кольорів. Ну, я думав, що це розумно! :-) Це звичайно економить велику кількість байтів.

Тому для перевірки цього коду вам потрібно буде перетворити вхідні зображення в 32-bpp растрові карти. Для цього не можна використовувати Windows Paint, оскільки він підтримує максимум 24 біти на піксель. Однак існує ряд інших програмних рішень, які можуть це зробити, наприклад Adobe Photoshop. Я використав цей безкоштовний інструмент , який перетворює PNG в BMP з 32-bpp в Windows, тобто означає, що вам потрібно конвертувати лише JPEG в PNG (що Paint може зробити).

Інші припущення, які я висловлюю, є надзвичайно обґрунтованими:

  • Припускається, що бітова карта має розмір більше 0 ( тобто передбачається , що вона містить принаймні один піксель). Це розумно, тому що, коли небо є недійсним, у нас є більші проблеми, ніж метеорологія.
  • Прапор напрямку ( DF) вважається чітким, тому ми будемо правильно повторювати растрову карту за допомогою LODSDінструкції. Це те саме припущення, яке роблять більшість конвенцій для викликів x86, тому здається справедливим. Якщо вам це не подобається, додайте 1 байт до рахунку для CLDінструкції.
  • Для режиму округлення для FPU x87 передбачається встановити значення «кругле до найближчого». Це гарантує, що ми отримуємо правильну поведінку, коли перетворюємо кількість октатів з тимчасової з плаваючою комою до кінцевого цілого результату, як це підтверджено тестовим випадком №4. Це припущення є обґрунтованим, оскільки це стан за замовчуванням для FPU, і його потрібно підтримувати навіть у коді С (де усічення - це поведінка округлення за замовчуванням, змушуючи компілятори, які бажають відповідати стандартам, щоб генерувати неефективний код, що змінює округлення режим, робить перетворення, а потім повертає режим округлення назад).

Невикольована збірна мнемоніка:

; 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

Математика 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.