Bagaimana Berawan?

22

Tantangan

Diberi gambar langit, Anda harus menampilkan tutupan awan dalam okta. Gambar yang disediakan akan menjadi file gambar (jenisnya terserah Anda) dan hasilnya harus STDOUT.

Oktas

Dalam meteorologi, okta adalah unit pengukuran yang digunakan untuk menggambarkan jumlah tutupan awan di lokasi tertentu seperti stasiun cuaca. Kondisi langit diperkirakan dalam hal berapa banyak per delapan langit ditutupi awan, mulai dari 0 oktas (langit sepenuhnya cerah) hingga 8 oktas (sepenuhnya mendung).

Langit akan selalu menjadi gambar dari sekitar tengah hari (jadi, langit biru, bukan langit merah / malam).

Warna cloud akan selalu menjadi warna yang mengikuti pola berikut:

#ABCDEF

Di mana AB >= C0, CD >= C0dan EF >= C0.

Atau, dalam RGB:

(A, B, C)

Di mana A >= 192, B >= 192dan C >= 192.

Berikut adalah persentase cakupan yang terkait dengan okta:

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

Persentase adalah persentase dari gambar yang cloud.

Jika Anda persentase cloud dari gambar Anda bukan kelipatan 12,5, Anda harus membulatkan ke terdekat.

Keluaran

Outputnya harus berupa angka okta (Anda tidak harus mengatakan unit).

Contohnya

1 okta (18.030743615677714% cloud)

0 okta (cloud 0,0%)

3 okta (cloud 42.66319444444445%)

1 okta (12.000401814778645% cloud)

Kode python digunakan untuk menghitung angka

Kemenangan

Kode terpendek dalam byte menang.

Peluruhan Beta
sumber
Bukankah yang terakhir 3 okta?
TheLethalCoder
@TheLethalCoder Whoops, diedit
Beta Decay
Apakah ada maksimum untuk dimensi gambar?
Shaggy
2
Saya telah menambahkan test case ke-4 yang membutuhkan pembulatan hingga 12,5, karena jawaban menggunakan integer flooring sudah melewati 3 test case pertama.
Justin Mariner
1
Tentang bahasa yang tidak memiliki kemampuan pemrosesan gambar seperti C ++, apakah boleh menggunakan perpustakaan? Jika demikian, untuk jumlah byte, haruskah hanya menghitung kode tertulis atau juga ukuran file DLL yang diperlukan untuk menjalankan program?
HatsuPointerKun

Jawaban:

10

Python 2 , 114 110 98 byte

-4 bytes berkat TheLethalCoder
-12 bytes berkat Ruud

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

Cobalah online!

tongkat
sumber
Gunakan 191sebagai gantinya?
TheLethalCoder
2
Saya akan menyarankan x&y&z&192>191, tetapi versi yang diperbarui sama singkatnya.
Arnauld
2
Bisakah Anda berpotensi mengganti import PIL.Image as Pdengan from PIL.Image import*dan menyimpan 1 byte saat berganti i=P.openke i=open? Saya tidak tahu apakah itu akan menyebabkan masalah karena terbuka sudah merupakan fungsi yang ditentukan, tetapi saya tidak dapat menguji karena saya tidak memiliki kemampuan untuk menginstal modul.
Arnold Palmer
1
Ya, itu sepertinya berhasil. Menghemat 1 byte.
Arfie
2
@Rod kode Anda tidak harus berjalan di semua platform - bahasa ditentukan oleh penerjemah. Jika berjalan untuk Anda maka itu valid.
Tim
10

MATL , 18 17 byte

Yi191>3&A1eYm8*Yo

Contoh dijalankan dengan empat gambar yang disediakan (maaf tentang kualitas pratinjau; klik untuk resolusi penuh):

masukkan deskripsi gambar di sini

Atau hapus empat karakter terakhir untuk melihat hasilnya tanpa pembulatan:

masukkan deskripsi gambar di sini

Penjelasan

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
Luis Mendo
sumber
Saya ingin tahu apa yang dapat dilakukan dengan menggunakan esolangs
Евгений Новиков
6

Java (OpenJDK 8) , 204 byte

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;}

Cobalah online! Saya selalu lupa bahwa TIO mengeluarkan STDERR ke tab debug .. Mungkin ini bisa seperti highlight merah jika ada kesalahan?

Roman Gräf
sumber
Beberapa hal: kode Anda saat ini berjalan dalam infinite loop, karena Anda tidak pernah menambah xatau y. Anda menetapkan y=0dua kali, sehingga Anda dapat menghapus tugas pertama. Kelas Colorharus sepenuhnya memenuhi syarat ( java.awt.Color) atau Anda harus memasukkan impor dalam jumlah byte Anda. Dan kode Anda gagal untuk test case ke-4 (menghasilkan 0 bukannya 1).
Justin Mariner
Saya tahu ini sudah lama, tetapi Anda bisa bermain golf 6 byte dengan menghapus tanda kurung bagian dalam untuk loop, dan mengubah &&to &dan ,y=0ke ,y: Cobalah online.
Kevin Cruijssen
6

C #, 150 146 byte

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

Disimpan 4 byte berkat @Ian H.

Versi Lengkap / Terformat:

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();
        }
    }
}
TheLethalCoder
sumber
for(h=0 h<b.Height;++t)Saya pikir Anda melewatkan titik koma di sana
Kritixi Lithos
2
Anda dapat mengganti /0.125dengan *8di akhir untuk menghemat beberapa byte.
Ian H.
@ Cowsquack Saya telah menghapus titik koma bukan spasi! Diperbaiki sekarang ..
TheLethalCoder
3

C #, 313 byte

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

Jelas lebih lama dari jawaban saya yang lain tetapi yang ini menggunakan LockBitsdan unsafekode untuk secara langsung mengakses gambar dalam memori; karena itu sangat cepat. Saya mungkin bisa menghapus panggilan UnlockBitstetapi itu lebih benar ada di sana.

Versi Lengkap / Terformat:

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();
        }
    }
}
TheLethalCoder
sumber
3

PowerShell , 200 byte

$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)

Mendapat input $args[0]sebagai path file gambar penuh, membangun New Bitmapobjek menjadi $a. Ini hanya nama objek internal; ini mendukung JPG, PNG, dll.

Kami kemudian loop ganda melalui .heightdan kemudian .widthgambar, menyentuh masing-masing pixel. Kami mencabut R,G,Bnilai-nilai dan kemudian memilih orang-orang yang -greaterthanor equal untuk 192dan pastikan bahwa countini 3(yaitu, semua dari mereka adalah putih-ish). Hasil Boolean itu ditambahkan ke akumulator kami $i.

Kami kemudian membagi untuk mendapatkan persentase, kalikan dengan 8untuk mendapatkan jumlah okta, dan kemudian [int]untuk mendapatkan hanya output integer. (Perhatikan bahwa ini melakukan Pembulatan Banker - jika itu tidak diizinkan, akan ada beberapa byte lagi untuk mengubah metode pembulatan.)

AdmBorkBork
sumber
2

dc, 74 byte

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

Input diambil sebagai file P3 ppm, dengan semua spasi putih sebagai baris baru. Output adalah ke STDOUT.

Cobalah online!

poi830
sumber
2

JavaScript, 83 77 byte

-6 bytes by 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)

Input

Gambar # 1

Gambar # 2

Gambar # 3

Gambar # 4

Demo

Евгений Новиков
sumber
1
Solusi yang sangat bagus Trik praktis dengan fungsi panah ES6 adalah membungkus segala sesuatu dalam tanda kurung, dipisahkan dengan koma ( a=>(b,c,d)) alih-alih melakukan a=>{b;c;return d}atau a=>eval("b;c;d"). Ini berfungsi kecuali jika Anda memiliki semacam loop, dalam hal ini Anda mungkin akan lebih baik menggunakan evalmetode ini.
ETHproduksi
2

C (POSIX), 103 byte

Mengasumsikan input sebagai file BMP di 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));}
yoann
sumber
2

Kode Mesin x86, 34 byte

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

Byte kode ini mendefinisikan fungsi yang mengambil input bitmap dan mengembalikan nilai integer yang mengindikasikan oktas-nya. Seperti dalam C , array (seperti bitmap) direpresentasikan sebagai pointer ke elemen pertama dan ukuran / panjang. Dengan demikian, fungsi ini mengambil dua parameter: jumlah piksel dalam bitmap (baris × kolom) dan pointer ke bitmap itu sendiri.

Kode ini menggunakan konvensi panggilan berbasis register kustom, di mana pointer bitmap dilewatkan dalam ESIregister dan ukuran bitmap dilewatkan dalam ECXregister. Hasilnya (oktas), seperti biasa, dikembalikan EAX.

Seperti yang sudah dinyatakan di atas, input diambil sebagai bitmap. Secara khusus, format 32-bpp digunakan, dalam format little-endian, tetapi kanal alfa (byte orde tertinggi) diabaikan. Ini menyederhanakan banyak hal, memungkinkan kita untuk hanya mengulangi setiap piksel dan memeriksa nilai warna RGB 32-bitnya. Optimalisasi cerdas juga digunakan di sini. Alih-alih mengisolasi setiap komponen warna dan memeriksa apakah itu adalah> = 192, kami hanya menutupi seluruh nilai 32-bit dengan 0xC0C0C0 dan menguji apakah hasilnya adalah> = 0xC0C0C0. Ini akan mengevaluasi true untuk semua warna "cloud", dan false untuk semua warna "sky" (non-cloud). Yah, saya pikir itu pintar! :-) Ini tentu saja menghemat banyak byte.

Oleh karena itu, untuk menguji kode ini, Anda harus mengubah gambar input menjadi bitmap 32-bpp. Anda tidak dapat menggunakan Windows Paint untuk ini, karena mendukung maksimum 24 bit per piksel. Namun, ada sejumlah solusi perangkat lunak lain yang dapat melakukannya, seperti Adobe Photoshop. Saya menggunakan alat gratis ini , yang mengubah PNG menjadi 32-bpp BMP di Windows, artinya Anda hanya perlu mengonversi dari JPEG ke PNG (yang dapat dilakukan Paint).

Asumsi lain yang saya anggap sangat masuk akal:

  • Bitmap diasumsikan memiliki ukuran lebih besar dari 0 ( yaitu , diasumsikan mengandung setidaknya satu piksel). Ini masuk akal karena, ketika langit nol, kita memiliki masalah yang lebih besar daripada meteorologi.
  • Bendera arah ( DF) diasumsikan jelas sehingga kita akan beralih dengan benar melalui bitmap menggunakan LODSDinstruksi. Ini adalah asumsi yang sama yang dibuat oleh kebanyakan konvensi pemanggilan x86, sehingga tampak adil. Jika Anda tidak menyukainya, tambahkan 1 byte ke hitungan untuk CLDinstruksi.
  • Mode pembulatan untuk FPU x87 diasumsikan disetel ke pembulatan ke terdekat. Ini memastikan bahwa kita mendapatkan perilaku yang benar ketika kita mengonversi jumlah okta dari floating-point sementara ke hasil integer akhir, seperti yang diverifikasi oleh uji kasus # 4. Asumsi ini masuk akal karena ini adalah keadaan default untuk FPU dan diharuskan untuk dipertahankan bahkan dalam kode C (di mana pemotongan adalah perilaku pembulatan standar, memaksa kompiler yang ingin memenuhi standar untuk menghasilkan kode tidak efisien yang mengubah pembulatan mode, lakukan konversi, dan kemudian ubah kembali mode pembulatan).

Mnemonik perakitan tidak dikumpulkan:

; 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

Tentunya Anda belum berhasil sampai sejauh ini dan masih bertanya-tanya bagaimana kodenya bekerja? :-)
Yah, ini sangat sederhana. Kami hanya mengulangi bitmap satu nilai 32-bit pada satu waktu, memeriksa untuk melihat apakah nilai RGB pixel "keruh" atau "tidak keruh". Jika mendung, kami menambah penghitung pra-nol kami. Pada akhirnya, kami menghitung: piksel berawantotal piksel  × 8
(yang setara dengan: piksel berawantotal piksel  ÷ 0,125).

Saya tidak dapat menyertakan tautan TIO untuk ini karena kebutuhan untuk memasukkan gambar. Namun, saya dapat memberi Anda harness yang saya gunakan untuk menguji ini pada 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;
}

Berhati-hatilah dengan ini! Seperti yang didefinisikan di atas, ComputeOktasmenggunakan konvensi pemanggilan kustom, yang tidak akan dihormati oleh kompiler C. Anda perlu menambahkan kode di bagian atas prosedur bahasa rakitan untuk memuat nilai dari tumpukan ke register yang diharapkan, misalnya :

mov  ecx, DWORD PTR [bmpSize]
mov  esi, DWORD PTR [bmpBits]
Cody Grey
sumber
1

JavaScript (ES6), 218 byte

(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

Mengambil Imageobjek sebagai input, yang dapat dibuat dari suatu <image>elemen.

Uji di sini di CodePen!

Alternatif

Jika input dapat diambil sebagai nilai rata-rata RGBA, dengan dimensi: 82 byte

(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

Format input ini sangat mirip dengan apa yang disarankan jawaban ini pada meta .

Justin Mariner
sumber
1

Mathematica 89 byte

Berikut ini binarize gambar dan menentukan sebagian kecil awan, yaitu piksel putih. Kemudian menentukan berapa kali .125 cocok dengan hasilnya. Ini mengembalikan lantai dari nilai itu.

o@i_:=⌊8Tr@Flatten[ImageData@MorphologicalBinarize[i,.932],1]/Times@@ImageDimensions@i⌋
DavidC
sumber