흐려 요?


22

도전

하늘 이미지가 제공되면 클라우드 커버를 oktas로 출력해야합니다. 제공된 이미지는 이미지 파일 (유형은 사용자에게 달려 있음)이며 출력은 STDOUT입니다.

옥 타스

기상학에서 okta는 기상 관측소와 같은 특정 위치에서 구름의 양을 설명하는 데 사용되는 측정 단위입니다. 하늘 상태는 0 옥 타스 (완전 맑은 하늘)에서 8 옥 타스 (완전 흐린 날씨)에 이르기까지 구름으로 덮힌 하늘의 8 분의 8의 관점에서 추정됩니다.

하늘은 항상 정오 (예 : 빨강 / 밤 하늘이 아닌 푸른 하늘)의 사진입니다.

구름의 색은 항상 다음 패턴을 따르는 색입니다.

#ABCDEF

어디에서 AB >= C0, CD >= C0그리고 EF >= C0.

또는 RGB로 :

(A, B, C)

어디에서 A >= 192, B >= 192그리고 C >= 192.

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

백분율은 이미지 인 이미지의 비율입니다.

이미지의 구름 비율이 12.5의 배수가 아닌 경우 가장 가까운 반올림해야합니다.

산출

출력은 단지 okta 번호 여야합니다 (장치를 말할 필요는 없습니다).

1 Okta (18.030743615677714 % 클라우드)

오 카타 0 (0.0 % 구름)

3 Oktas (42.66319444444445 % 클라우드)

1 Okta (12.000401814778645 % 클라우드)

숫자를 계산하는 데 사용되는 파이썬 코드

승리

바이트 단위의 최단 코드가 이깁니다.


마지막 3 개의 oktas 아닌가요?
TheLethalCoder

@TheLethalCoder Whoops, 편집
베타 부패

이미지의 최대 크기가 있습니까?
얽히고 설킨

2
정수 바닥을 사용하는 답변이 처음 세 가지 테스트 사례를 통과했기 때문에 12.5로 반올림 해야하는 4 번째 테스트 사례를 추가했습니다.
Justin Mariner

1
C ++과 같은 이미지 처리 기능이없는 언어에 대해서는 라이브러리를 사용해도 괜찮습니까? 그렇다면 바이트 수의 경우 작성된 ​​코드 또는 프로그램 실행에 필요한 DLL 파일의 크기 만 계산해야합니까?
HatsuPointerKun

답변:


10

파이썬 (2) , 114 (110) 98 바이트

TheLethalCoder 덕분에 -4 바이트
Ruud 덕분에 -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것이지만 업데이트 된 버전은 짧습니다.
Arnauld

2
당신은 잠재적으로 대체 할 수 import PIL.Image as Pfrom PIL.Image import*변경하는 경우 1 바이트를 저장 i=P.openi=open? open이 이미 정의 된 기능이므로 문제가 발생하는지 모르겠지만 모듈을 설치할 수 없으므로 테스트 할 수 없습니다.
Arnold Palmer

1
그래, 그것은 작동하는 것 같습니다. 1 바이트를 저장합니다.
Arfie

2
@Rod 코드가 모든 플랫폼에서 실행될 필요는 없습니다. 언어는 인터프리터에 의해 정의됩니다. 그것이 당신을 위해 실행되면 유효합니다.
Tim

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

자바 (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있거나 ( ) 바이트 수에 가져 오기를 포함해야합니다. 그리고 네 번째 테스트 사례에서는 코드가 실패합니다 (1 대신 0을 반환 함).
Justin Mariner

나는 동안이었다 알고 있지만, 할 수 있습니다에 대한 루프 내부의 브래킷을 제거하고,을 변경하여 6 바이트 골프 &&&,y=0,y: 온라인으로보십시오.
Kevin Cruijssen

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

@Ian H 덕분에 4 바이트를 절약했습니다.

풀 / 포맷 버전 :

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)세미콜론을 놓친 것 같습니다
Kritixi Lithos

2
당신은을 대체 할 수 /0.125*8몇 바이트를 저장하는 말.
Ian H.

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

물론 더 이상 내 다른 대답보다 더 그러나 이것은 사용 LockBitsunsafe직접 메모리에 이미지에 액세스하는 코드; 따라서 엄청나게 빠릅니다. 아마도 전화를 제거 할 수는 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 e에 QUAL을 192확인하십시오 및 확인 count된다 3(즉, 그들 모두 흰색 틱이됩니다). 그 부울 결과는 누산기에 추가됩니다 $i.

그런 다음 백분율을 얻기 위해 나누고 8oktas 수를 곱한 다음 [int]정수 출력을 얻습니다. (이는 Banker 's Rounding을 수행합니다. 허용되지 않으면 반올림 방법을 변경하는 데 몇 바이트 더 필요합니다.)


2

dc, 74 바이트

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

입력은 모든 공백을 개행 문자로하여 P3 ppm 파일로 가져옵니다. 출력은 STDOUT입니다.

온라인으로 사용해보십시오!


2

자바 스크립트, 83 77 바이트

ETHproductions -6 바이트

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 바이트

stdin에서 입력을 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

이 코드 바이트는 비트 맵 입력을 가져와 해당 oktas를 나타내는 정수 값을 반환하는 함수를 정의합니다. C 에서처럼 비트 맵과 같은 배열은 첫 번째 요소에 대한 포인터와 크기 / 길이로 표시됩니다. 따라서이 함수는 비트 맵의 ​​총 픽셀 수 (행 × 열)와 비트 맵 자체에 대한 포인터의 두 가지 매개 변수를 사용합니다.

이 코드는 사용자 정의 레지스터 기반 호출 규칙을 사용합니다. 여기서 비트 맵 포인터는 ESI레지스터에 전달되고 비트 맵 크기는 ECX레지스터에 전달됩니다 . 결과 (oktas)는 평소대로로 반환됩니다 EAX.

위에서 이미 언급했듯이 입력은 비트 맵으로 사용됩니다. 특히 32bpp 형식이 리틀 엔디안 형식으로 사용되지만 알파 채널 (최고 바이트)은 무시됩니다. 이를 통해 많은 작업을 단순화하여 각 픽셀을 간단히 반복하고 32 비트 RGB 색상 값을 확인할 수 있습니다. 영리한 최적화도 여기에서 사용됩니다. 각 색상 구성 요소를 분리하고> = 192인지 확인하는 대신 전체 32 비트 값을 0xC0C0C0으로 마스킹하고 결과가> = 0xC0C0C0인지 테스트합니다. 모든 "구름"색상의 경우 true로 평가되고 모든 "하늘"(비구름) 색상의 경우 false로 평가됩니다. 글쎄, 나는 그것이 영리하다고 생각했다! :-) 확실히 많은 수의 바이트를 저장합니다.

따라서이 코드를 테스트하려면 입력 이미지를 32bpp 비트 맵으로 변환해야합니다. 픽셀 당 최대 24 비트를 지원하므로 Windows Paint를 사용할 수 없습니다. 그러나 Adobe Photoshop과 같은 다른 소프트웨어 솔루션도 있습니다. 필자 는 Windows에서 PNG를 32bpp BMP로 변환하는 이 무료 도구를 사용 했습니다 . 즉, JPEG에서 PNG로만 변환하면됩니다 (페인트 가능).

내가 주장하는 다른 가정은 명백히 합리적입니다.

  • 비트 맵은 0보다 큰 크기를 갖는 것으로 가정된다 ( , 적어도 하나의 픽셀을 포함하는 것으로 가정 됨). 하늘이 널 때 기상학보다 더 큰 문제가 있기 때문에 이것은 합리적입니다.
  • 방향 플래그 ( DF)는 LODSD명령을 사용하여 비트 맵을 올바르게 반복 할 수 있도록 명확하다고 가정합니다 . 이것은 대부분의 x86 호출 규칙과 동일한 가정이므로 공정한 것 같습니다. 마음에 들지 않으면 CLD명령어 수에 1 바이트를 추가하십시오 .
  • x87 FPU의 반올림 모드는 가장 가까운 반올림으로 설정된 것으로 가정합니다. 이를 통해 테스트 사례 # 4에서 확인한 것처럼 oktas 수를 부동 소수점 임시에서 최종 정수 결과로 변환 할 때 올바른 동작을 얻을 수 있습니다. 이것은 FPU의 기본 상태이기 때문에이 가정은 타당 하고 소원 라운딩을 변경 비효율적 인 코드를 생성하는 표준을 준수 할 것을 컴파일러를 강요, 심지어 절단은 기본 동작을 반올림되는 C 코드 (유지 될 필요가 모드에서 변환을 수행 한 다음 반올림 모드를 다시 변경합니다).

ungolfed 어셈블리 니모닉 :

; 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

확실히 당신은이 방법으로 그것을 만들지 않았고 여전히 코드가 어떻게 작동하는지 궁금합니다? :-)
글쎄요, 꽤 간단합니다. 픽셀 RGB 값이 "흐리게"또는 "흐리게"아닌지 확인하여 비트 맵을 한 번에 하나의 32 비트 값으로 반복합니다. 흐린 경우 사전 영점 카운터를 증가시킵니다. 결국, 우리는 흐린 픽셀총 픽셀  × 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;
}

그래도 조심하십시오! 위에서 정의한대로 ComputeOktasC 컴파일러가 존중하지 않는 사용자 지정 호출 규칙을 사용합니다. 스택에서 예상 레지스터로 값을로드하려면 어셈블리 언어 프로 시저 상단에 코드를 추가해야합니다. :

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

1

자바 스크립트 (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⌋
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.