Làm thế nào nhiều mây?


22

Thử thách

Đưa ra một hình ảnh của bầu trời, bạn phải xuất ra đám mây trong oktas. Hình ảnh được cung cấp sẽ là một tệp hình ảnh (loại tùy thuộc vào bạn) và đầu ra phải là STDOUT.

Oktas

Trong khí tượng học, okta là một đơn vị đo lường được sử dụng để mô tả lượng mây che phủ tại bất kỳ vị trí nào như trạm thời tiết. Các điều kiện bầu trời được ước tính theo khoảng bao nhiêu phần tám của bầu trời được bao phủ trong đám mây, từ 0 oktas (bầu trời hoàn toàn rõ ràng) cho đến 8 oktas (hoàn toàn u ám).

Bầu trời sẽ luôn là một bức tranh từ khoảng giữa trưa (vì vậy, bầu trời xanh, không phải màu đỏ / bầu trời đêm).

Màu của đám mây sẽ luôn là màu theo mẫu sau:

#ABCDEF

Ở đâu AB >= C0, CD >= C0EF >= C0.

Hoặc, trong RGB:

(A, B, C)

Ở đâu A >= 192, B >= 192C >= 192.

Dưới đây là tỷ lệ phần trăm liên quan đến oktas:

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

Tỷ lệ phần trăm là tỷ lệ phần trăm của hình ảnh là đám mây.

Nếu bạn phần trăm đám mây của hình ảnh của bạn không phải là bội số của 12,5, bạn nên làm tròn đến gần nhất.

Đầu ra

Đầu ra chỉ nên là số okta (bạn không cần phải nói đơn vị).

Ví dụ

1 okta (18.030743615677714% đám mây)

0 oktas (đám mây 0,0%)

3 oktas (42.66319444444445% đám mây)

1 okta (12.000401814778645% đám mây)

Mã Python dùng để tính số

Chiến thắng

Mã ngắn nhất trong byte thắng.


Không phải là 3 oktas cuối cùng sao?
TheLethalCoder

@TheLethalCoder Rất tiếc, đã được chỉnh sửa
Beta Decay

Có tối đa kích thước của một hình ảnh?
Xù xì

2
Tôi đã thêm trường hợp thử nghiệm thứ 4 yêu cầu làm tròn đến 12,5, vì các câu trả lời sử dụng sàn số nguyên sẽ vượt qua 3 trường hợp thử nghiệm đầu tiên.
Justin Mariner

1
Về các ngôn ngữ không có khả năng xử lý hình ảnh như C ++, sử dụng thư viện có ổn không? Nếu vậy, đối với số byte, nó chỉ nên đếm mã bằng văn bản hoặc kích thước của tệp DLL cần thiết để chạy chương trình?
HatsuPulumKun 28/07/17

Câu trả lời:


10

Python 2 , 114 110 98 byte

-4 byte nhờ TheLethalCoder
-12 byte nhờ Ruud

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

Hãy thử trực tuyến!


Sử dụng 191thay thế?
TheLethalCoder

2
Tôi sẽ đề nghị x&y&z&192>191, nhưng phiên bản cập nhật chỉ là ngắn.
Arnauld

2
Bạn có thể thay thế import PIL.Image as Pbằng from PIL.Image import*và lưu 1 byte khi thay đổi i=P.openthành i=open? Tôi không biết điều đó có gây ra sự cố hay không vì mở đã là một chức năng được xác định, nhưng tôi không thể kiểm tra vì tôi không có khả năng cài đặt mô-đun.
Arnold Palmer

1
Vâng, điều đó dường như làm việc. Tiết kiệm 1 byte.
Arfie

2
@Rod mã của bạn không phải chạy trên tất cả các nền tảng - ngôn ngữ được xác định bởi trình thông dịch. Nếu nó chạy cho bạn thì nó hợp lệ.
Tim

10

MATL , 18 17 byte

Yi191>3&A1eYm8*Yo

Ví dụ chạy với bốn hình ảnh được cung cấp (xin lỗi về chất lượng xem trước; nhấp để có độ phân giải đầy đủ):

nhập mô tả hình ảnh ở đây

Hoặc xóa bốn ký tự cuối cùng để xem kết quả mà không làm tròn:

nhập mô tả hình ảnh ở đây

Giải trình

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

Tôi tự hỏi những gì có thể được thực hiện bằng 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;}

Hãy thử trực tuyến! Tôi luôn quên rằng TIO xuất STDERR sang tab gỡ lỗi .. Có lẽ nó có thể thích màu đỏ nổi bật trong trường hợp có lỗi?


Vài điều: mã của bạn hiện đang chạy trong một vòng lặp vô hạn, vì bạn không bao giờ tăng xhoặc y. Bạn đã chỉ định y=0hai lần, vì vậy bạn có thể loại bỏ nhiệm vụ đầu tiên. Lớp Colorphải đủ tiêu chuẩn ( java.awt.Color) hoặc bạn phải bao gồm nhập trong số byte của bạn. Và mã của bạn không thành công cho trường hợp thử nghiệm thứ 4 (trả về 0 thay vì 1).
Justin Mariner

Tôi biết đã được một lúc, nhưng bạn có thể đánh gôn 6 byte bằng cách xóa dấu ngoặc của vòng lặp for bên trong và thay đổi &&thành &,y=0thành ,y: Thử trực tuyến.
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);}

Đã lưu 4 byte nhờ @Ian H.

Phiên bản đầy đủ / được định dạng:

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)Tôi nghĩ rằng bạn đã bỏ lỡ một dấu chấm phẩy ở đó
Kritixi Lithos

2
Bạn có thể thay thế /0.125bằng *8ở cuối để lưu một vài byte.
Ian H.

@Cowsquack Tôi đã xóa dấu chấm phẩy thay vì dấu cách! Đã sửa ngay bây giờ ..
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);}}}

Rõ ràng dài hơn câu trả lời khác của tôi nhưng câu này sử dụng LockBitsunsafemã để truy cập trực tiếp vào hình ảnh trong bộ nhớ; như vậy là rất nhanh Tôi có thể có thể loại bỏ cuộc gọi đến UnlockBitsnhưng nó chính xác hơn với nó ở đó.

Phiên bản đầy đủ / được định dạng:

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

Nhận đầu vào $args[0]là đường dẫn tệp hình ảnh đầy đủ, xây dựng một New Bitmapđối tượng vào $a. Đây chỉ là tên đối tượng nội bộ; nó hỗ trợ JPG, PNG, v.v.

Sau đó, chúng tôi lặp đôi qua .heightvà sau đó .widthlà hình ảnh, chạm vào nhau pixel. Chúng tôi kéo ra các R,G,Bgiá trị và sau đó chọn những người được -greaterthanor equal tới 192và chắc chắn rằng countđược 3(ví dụ, tất cả chúng đều trắng-ish). Kết quả Boolean đó được thêm vào bộ tích lũy của chúng tôi $i.

Sau đó chúng tôi chia ra để lấy tỷ lệ phần trăm, nhân nó 8với số lượng oktas và sau đó [int]chỉ lấy một đầu ra số nguyên. (Lưu ý rằng điều này thực hiện Làm tròn Ngân hàng - nếu điều đó không được phép thì sẽ có thêm một vài byte để thay đổi phương thức làm tròn.)


2

dc, 74 byte

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

Đầu vào được lấy dưới dạng tệp p3 P3, với tất cả khoảng trắng là dòng mới. Đầu ra là STDOUT.

Hãy thử trực tuyến!


2

JavaScript, 83 77 byte

-6 byte bởi 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)

Đầu vào

Bức tranh 1

Ảnh số 2

Ảnh số 3

Hình số 4

Bản giới thiệu


1
Giải pháp rất hay. Một mẹo hữu ích với các hàm mũi tên ES6 là bọc mọi thứ trong ngoặc đơn, phân tách bằng dấu phẩy ( a=>(b,c,d)) thay vì thực hiện a=>{b;c;return d}hoặc a=>eval("b;c;d"). Điều này hoạt động trừ khi bạn có một vòng lặp nào đó, trong trường hợp đó có lẽ bạn sẽ sử dụng tốt nhất evalphương pháp này.
Sản phẩm ETH

2

C (POSIX), 103 byte

Giả sử đầu vào là tệp BMP trên 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

Mã máy 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

Các byte mã này xác định một hàm lấy đầu vào bitmap và trả về một giá trị nguyên cho biết oktas của nó. Như trong C , các mảng (như bitmap) được biểu diễn dưới dạng con trỏ đến phần tử đầu tiên và kích thước / chiều dài. Do đó, hàm này có hai tham số: tổng số pixel trong bitmap (cột × cột) và một con trỏ tới chính bitmap.

Mã này sử dụng quy ước gọi dựa trên thanh ghi tùy chỉnh, trong đó con trỏ bitmap được truyền trong thanh ESIghi và kích thước bitmap được truyền trong thanh ECXghi. Kết quả (oktas) là, thông thường, được trả lại EAX.

Như đã nêu ở trên, đầu vào được lấy dưới dạng bitmap. Cụ thể, định dạng 32 bpp được sử dụng, ở định dạng cuối nhỏ, nhưng kênh alpha (byte thứ tự cao nhất) bị bỏ qua. Điều này đơn giản hóa rất nhiều thứ, cho phép chúng ta chỉ cần lặp lại qua từng pixel và kiểm tra giá trị màu RGB 32 bit của nó. Một tối ưu hóa thông minh cũng được sử dụng ở đây. Thay vì cô lập từng thành phần màu và kiểm tra xem nó có> = 192 hay không, chúng ta chỉ che dấu toàn bộ giá trị 32 bit bằng 0xC0C0C0 và kiểm tra xem kết quả có> = 0xC0C0C0 hay không. Điều này sẽ đánh giá đúng với tất cả các màu "đám mây" và sai cho tất cả các màu "bầu trời" (không phải đám mây). Chà, tôi nghĩ nó thật thông minh! :-) Nó chắc chắn tiết kiệm một số lượng lớn byte.

Do đó, để kiểm tra mã này, bạn sẽ cần phải chuyển đổi hình ảnh đầu vào thành bitmap 32 bpp. Bạn không thể sử dụng Windows Paint cho việc này vì nó hỗ trợ tối đa 24 bit cho mỗi pixel. Tuy nhiên, có một số giải pháp phần mềm khác có thể làm điều đó, chẳng hạn như Adobe Photoshop. Tôi đã sử dụng công cụ miễn phí này để chuyển đổi PNG thành BMP 32 bpp trên Windows, nghĩa là bạn chỉ cần chuyển đổi từ JPEG sang PNG (điều mà Paint có thể làm).

Các giả định khác mà tôi đặt ra là rất hợp lý:

  • Bitmap được giả sử là có kích thước lớn hơn 0 ( nghĩa là , nó được giả sử có chứa ít nhất một pixel). Điều này là hợp lý bởi vì, khi bầu trời của chúng là null, chúng ta có vấn đề lớn hơn khí tượng học.
  • Cờ hướng ( DF) được giả sử là rõ ràng để chúng ta sẽ lặp lại chính xác thông qua bitmap bằng cách sử dụng LODSDhướng dẫn. Đây là giả định tương tự được thực hiện bởi hầu hết các quy ước gọi x86, vì vậy nó có vẻ công bằng. Nếu bạn không thích nó, hãy thêm 1 byte vào số đếm choCLD hướng dẫn.
  • Chế độ làm tròn cho FPU x87 được giả sử là được đặt thành làm tròn đến gần nhất-chẵn. Điều này đảm bảo rằng chúng tôi có được hành vi chính xác khi chúng tôi chuyển đổi số lượng oktas từ tạm thời dấu phẩy động sang kết quả số nguyên cuối cùng, như được xác minh bởi trường hợp thử nghiệm # 4. Giả định này là hợp lý bởi vì đây là trạng thái mặc định cho FPU nó được yêu cầu duy trì ngay cả trong mã C (trong đó cắt ngắn là hành vi làm tròn mặc định, buộc các trình biên dịch muốn tuân thủ tiêu chuẩn để tạo mã không hiệu quả làm thay đổi làm tròn chế độ, thực hiện chuyển đổi, và sau đó thay đổi chế độ làm tròn trở lại).

Ma thuật lắp ráp bất khả xâm phạm:

; 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

Chắc chắn bạn đã không làm cho nó xuống hết mức và vẫn đang tự hỏi làm thế nào mã hoạt động? :-)
Chà, nó khá đơn giản. Chúng tôi chỉ lặp lại thông qua bitmap một giá trị 32 bit tại một thời điểm, kiểm tra xem liệu giá trị RGB pixel đó là "mây" hay "không mây". Nếu trời nhiều mây, chúng tôi sẽ tăng bộ đếm trước không. Cuối cùng, chúng tôi tính toán: pixel pixeltổng pixel  × 8
(tương đương với: pixel mâytổng pixel  0.125).

Tôi không thể bao gồm một liên kết TIO cho việc này vì nhu cầu về hình ảnh đầu vào. Tuy nhiên, tôi có thể cung cấp cho bạn khai thác mà tôi đã sử dụng để kiểm tra điều này trên 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;
}

Hãy cẩn thận với điều này, mặc dù! Như đã định nghĩa ở trên, ComputeOktassử dụng quy ước gọi tùy chỉnh mà trình biên dịch C sẽ không tôn trọng. Bạn cần thêm mã ở đầu quy trình ngôn ngữ lắp ráp để tải các giá trị từ ngăn xếp vào các thanh ghi dự kiến, ví dụ :

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

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

Lấy một Imageđối tượng làm đầu vào, có thể được tạo từ một <image>phần tử.

Kiểm tra nó ở đây trên CodePen!

Thay thế

Nếu đầu vào có thể được coi là mảng phẳng của các giá trị RGBA, với kích thước: 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

Định dạng đầu vào này rất giống với những gì câu trả lời này trên meta gợi ý.


1

Toán học 89 byte

Sau đây, nhị phân hình ảnh và xác định tỷ lệ các đám mây, tức là các pixel trắng. Sau đó, nó xác định bao nhiêu lần .125 phù hợp với kết quả. Nó trả về sàn của giá trị đó.

o@i_:=⌊8Tr@Flatten[ImageData@MorphologicalBinarize[i,.932],1]/Times@@ImageDimensions@i⌋
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.