¿Qué tan nublado está?

22

Reto

Dada una imagen del cielo, debe mostrar la capa de nubes en octas. La imagen suministrada será un archivo de imagen (el tipo depende de usted) y la salida debe ser STDOUT.

Oktas

En meteorología, un okta es una unidad de medida utilizada para describir la cantidad de cobertura de nubes en cualquier lugar dado, como una estación meteorológica. Las condiciones del cielo se estiman en términos de cuántos octavos del cielo están cubiertos de nubes, desde 0 octas (cielo completamente despejado) hasta 8 octas (completamente nublado).

El cielo siempre será una imagen de alrededor del mediodía (por lo tanto, cielo azul, no rojo / cielo nocturno).

El color de una nube siempre será un color que siga el siguiente patrón:

#ABCDEF

Donde AB >= C0, CD >= C0y EF >= C0.

O, en RGB:

(A, B, C)

Donde A >= 192, B >= 192y C >= 192.

Aquí están los porcentajes de cobertura relacionados con los 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

Los porcentajes son el porcentaje de la imagen que es nube.

Si el porcentaje de nube de su imagen no es múltiplo de 12.5, debe redondear al más cercano.

Salida

La salida solo debe ser el número okta (no tiene que decir la unidad).

Ejemplos

1 octa (18.030743615677714% nube)

0 octas (0.0% nube)

3 octas (42.66319444444445% nube)

1 octa (12.000401814778645% nube)

Código de Python usado para calcular números

Victorioso

El código más corto en bytes gana.

Decaimiento Beta
fuente
¿No son los últimos 3 octas?
TheLethalCoder
@TheLethalCoder Whoops, editado
Beta Decay
¿Hay un máximo en las dimensiones de una imagen?
Shaggy
2
Agregué un cuarto caso de prueba que requiere redondear a 12.5, ya que las respuestas que usan pisos enteros habrían pasado los primeros 3 casos de prueba.
Justin Mariner
1
Acerca de los lenguajes que no tienen capacidades de procesamiento de imágenes como C ++, ¿está bien usar una biblioteca? Si es así, para el recuento de bytes, ¿debería contar solo el código escrito o también el tamaño de los archivos DLL necesarios para ejecutar el programa?
HatsuPointerKun

Respuestas:

10

Python 2 , 114 110 98 bytes

-4 bytes gracias a TheLethalCoder
-12 bytes gracias a Ruud

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

Pruébalo en línea!

Barra
fuente
Usar en su 191lugar?
TheLethalCoder
2
Iba a sugerir x&y&z&192>191, pero la versión actualizada es igual de breve.
Arnauld
2
¿Podría potencialmente reemplazar import PIL.Image as Pcon from PIL.Image import*y guardar 1 byte cuando se cambia i=P.opena i=open? No sé si eso causaría problemas ya que abrir ya es una función definida, pero no puedo probarlo porque no tengo la capacidad de instalar el módulo.
Arnold Palmer
1
Sí, eso parece funcionar. Ahorra 1 byte.
Arfie
2
@ Rod su código no tiene que ejecutarse en todas las plataformas: el intérprete define el idioma. Si se ejecuta para usted, entonces es válido.
Tim
10

MATL , 18 17 bytes

Yi191>3&A1eYm8*Yo

El ejemplo se ejecuta con las cuatro imágenes proporcionadas (perdón por la calidad de la vista previa; haga clic para obtener la resolución completa):

ingrese la descripción de la imagen aquí

O elimine los últimos cuatro caracteres para ver los resultados sin redondear:

ingrese la descripción de la imagen aquí

Explicación

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
fuente
Me pregunto qué se puede hacer usando esolangs
Евгений Новиков
6

Java (OpenJDK 8) , 204 bytes

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

Pruébalo en línea! Siempre olvido que TIO envía STDERR a la pestaña de depuración. ¿Tal vez podría resaltar el rojo en caso de error?

Roman Gräf
fuente
Pocas cosas: su código actualmente se ejecuta en un bucle infinito, ya que nunca incrementa xo y. Usted asignó y=0dos veces, por lo que puede eliminar la primera asignación. La clase Colordebe estar completamente calificada ( java.awt.Color) o debe incluir la importación en su recuento de bytes. Y su código falla para el cuarto caso de prueba (devuelve 0 en lugar de 1).
Justin Mariner
Sé que ha pasado un tiempo, pero puedes jugar al golf 6 bytes quitando los corchetes del bucle for interno y cambiando el &&a &y ,y=0para ,y: Pruébalo en línea.
Kevin Cruijssen
6

C #, 150 146 bytes

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

Guardado 4 bytes gracias a @Ian H.

Versión completa / formateada:

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
fuente
for(h=0 h<b.Height;++t)Creo que te perdiste un punto y coma allí
Kritixi Lithos
2
Puede reemplazar el /0.125con *8al final para guardar algunos bytes.
Ian H.
@Cowsquack ¡Había eliminado el punto y coma en lugar del espacio! Reparado ahora ..
TheLethalCoder
3

C #, 313 bytes

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

Obviamente, ya que mi otra respuesta, pero éste usos LockBitsy unsafecódigo para acceder directamente a la imagen en la memoria; Como tal, es increíblemente rápido. Probablemente podría eliminar la llamada a UnlockBitspero es más correcto allí.

Versión completa / formateada:

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
fuente
3

PowerShell , 200 bytes

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

Obtiene entrada $args[0] como la ruta de archivo de imagen completa, construye un New Bitmapobjeto en $a. Este es solo el nombre interno del objeto; Es compatible con JPG, PNG, etc.

Luego hacemos un doble bucle a través de .heighty luego el .widthde la imagen, tocando cada uno pixel. Extraemos los R,G,Bvalores y luego seleccionamos aquellos que son -greales eo no192 y asegúrese de que countestá 3(es decir, todos ellos son de color blanco-ish). Ese resultado booleano se agrega a nuestro acumulador $i.

Luego nos dividimos para obtener el porcentaje, lo multiplicamos por 8para obtener el número de octas y luego [int]para obtener solo una salida entera. (Tenga en cuenta que esto realiza el redondeo bancario; si no está permitido, habrá varios bytes más para cambiar el método de redondeo).

AdmBorkBork
fuente
2

cc, 74 bytes

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

La entrada se toma como un archivo P3 ppm, con todos los espacios en blanco como líneas nuevas. La salida es STDOUT.

Pruébalo en línea!

poi830
fuente
2

JavaScript, 83 77 bytes

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

Entradas

Foto 1

Imagen # 2

Imagen # 3

Imagen # 4

Manifestación

Евгений Новиков
fuente
1
Muy buena solución. Un truco útil con las funciones de flecha de ES6 es envolver todo entre paréntesis, separados por comas ( a=>(b,c,d)) en lugar de hacer a=>{b;c;return d}o a=>eval("b;c;d"). Esto funciona a menos que tenga un bucle de algún tipo, en cuyo caso probablemente sea mejor usar el evalmétodo.
ETHproductions
2

C (POSIX), 103 bytes

Asume la entrada como archivo BMP en 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
fuente
2

Código de máquina x86, 34 bytes

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

Estos bytes de código definen una función que toma una entrada de mapa de bits y devuelve un valor entero que indica sus octas. Como en C , las matrices (como los mapas de bits) se representan como un puntero al primer elemento y un tamaño / longitud. Por lo tanto, esta función toma dos parámetros: el número total de píxeles en el mapa de bits (filas × columnas) y un puntero al mapa de bits en sí.

Este código utiliza una convención de llamada personalizada basada en registros, donde el puntero de mapa de bits se pasa en el ESIregistro y el tamaño del mapa de bits se pasa en el ECXregistro. El resultado (oktas) es, como siempre, devuelto EAX.

Como ya se indicó anteriormente, la entrada se toma como un mapa de bits. Específicamente, se utiliza un formato de 32 bpp, en un formato little-endian, pero se ignora el canal alfa (byte de orden superior). Esto simplifica muchas cosas, permitiéndonos simplemente recorrer cada píxel y verificar su valor de color RGB de 32 bits. Aquí también se usa una optimización inteligente. En lugar de aislar cada componente de color y verificar si es> = 192, simplemente enmascaramos el valor completo de 32 bits por 0xC0C0C0 y probamos si el resultado es> = 0xC0C0C0. Esto se evaluará como verdadero para todos los colores "nubosos" y falso para todos los colores "celestes" (que no sean nubes). Bueno, ¡ pensé que era inteligente! :-) Ciertamente ahorra una gran cantidad de bytes.

Por lo tanto, para probar este código, deberá convertir las imágenes de entrada a mapas de bits de 32 bpp. No puede usar Windows Paint para esto, ya que admite un máximo de 24 bits por píxel. Sin embargo, hay varias otras soluciones de software que pueden hacerlo, como Adobe Photoshop. Utilicé esta herramienta gratuita , que convierte un PNG a un BMP de 32 bpp en Windows, lo que significa que solo necesita convertir de JPEG a PNG (que Paint puede hacer).

Otros supuestos que considero son eminentemente razonables:

  • Se supone que el mapa de bits tiene un tamaño mayor que 0 ( es decir , se supone que contiene al menos un píxel). Esto es razonable porque, cuando el cielo es nulo, tenemos mayores problemas que la meteorología.
  • Se DFsupone que la bandera de dirección ( ) es clara, de modo que iteraremos correctamente a través del mapa de bits utilizando la LODSDinstrucción. Esta es la misma suposición hecha por la mayoría de las convenciones de llamadas x86, por lo que parece justo. Si no le gusta, agregue 1 byte al conteo para una CLDinstrucción.
  • Se supone que el modo de redondeo para la FPU x87 se establece en redondear a la par más cercana. Esto garantiza que obtengamos el comportamiento correcto cuando convertimos el número de octas de un punto flotante temporal al resultado entero final, como se verifica en el caso de prueba # 4. Esta suposición es razonable porque este es el estado predeterminado para la FPU y debe mantenerse incluso en el código C (donde el truncamiento es el comportamiento de redondeo predeterminado, lo que obliga a los compiladores que desean cumplir con los estándares a generar código ineficiente que cambia el redondeo modo, realiza la conversión y luego vuelve a cambiar el modo de redondeo).

Mnemónicos de ensamblaje sin golf:

; 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

¿Seguramente no has llegado hasta aquí y todavía te preguntas cómo funciona el código? :-)
Bueno, es bastante simple. Simplemente iteramos a través del mapa de bits un valor de 32 bits a la vez, verificando si ese valor RGB de píxel está "nublado" o "no nublado". Si está nublado, incrementamos nuestro contador pre-cero. Al final, calculamos: píxeles nubladospíxeles totales  × 8
(que es equivalente a: píxeles nubladospíxeles totales  ÷ 0.125).

No puedo incluir un enlace TIO para esto debido a la necesidad de imágenes de entrada. Sin embargo, puedo proporcionarle el arnés que utilicé para probar esto en 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;
}

¡Pero ten cuidado con esto! Como se definió anteriormente, ComputeOktasutiliza una convención de llamada personalizada, que un compilador de C no respetará. Debe agregar código en la parte superior del procedimiento del lenguaje ensamblador para cargar valores de la pila en los registros esperados, por ejemplo :

mov  ecx, DWORD PTR [bmpSize]
mov  esi, DWORD PTR [bmpBits]
Cody Gray
fuente
1

JavaScript (ES6), 218 bytes

(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

Toma un Imageobjeto como entrada, que se puede crear a partir de un <image>elemento.

¡Pruébalo aquí en CodePen!

Alternativa

Si la entrada se puede tomar como una matriz plana de valores RGBA, con dimensiones: 82 bytes

(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

Este formato de entrada es muy similar a lo que sugiere esta respuesta en meta .

Justin Mariner
fuente
1

Mathematica 89 bytes

Lo siguiente binariza la imagen y determina la fracción de nubes, es decir, píxeles blancos. Luego determina cuántas veces .125 cabe en el resultado. Devuelve el piso de ese valor.

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