Comment est-il nuageux?

22

Défi

Étant donné une image du ciel, vous devez afficher la couverture nuageuse en octas. L'image fournie sera un fichier image (le type dépend de vous) et la sortie devrait être vers STDOUT.

Oktas

En météorologie, un okta est une unité de mesure utilisée pour décrire la quantité de couverture nuageuse à un endroit donné, comme une station météorologique. Les conditions du ciel sont estimées en termes de combien de huitièmes du ciel sont couverts de nuages, allant de 0 octas (ciel complètement clair) à 8 octas (complètement couvert).

Le ciel sera toujours une image d'environ midi (donc, ciel bleu, pas rouge / ciel nocturne).

La couleur d'un nuage sera toujours une couleur qui suit le motif suivant:

#ABCDEF

AB >= C0, CD >= C0et EF >= C0.

Ou, en RVB:

(A, B, C)

A >= 192, B >= 192et C >= 192.

Voici les pourcentages de couverture liés aux octas:

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

Les pourcentages sont le pourcentage de l'image qui est un nuage.

Si le pourcentage de nuage de votre image n'est pas un multiple de 12,5, vous devez arrondir au plus proche.

Sortie

La sortie doit simplement être le nombre okta (vous n'avez pas besoin de dire l'unité).

Exemples

1 okta (18.030743615677714% cloud)

0 octas (0,0% nuage)

3 octas (42.66319444444445% cloud)

1 okta (12.000401814778645% cloud)

Code Python utilisé pour calculer les nombres

Gagnant

Le code le plus court en octets gagne.

Beta Decay
la source
Le dernier n'est-il pas 3 octas?
TheLethalCoder
@TheLethalCoder Whoops, édité
Beta Decay
Y a-t-il un maximum aux dimensions d'une image?
Shaggy
2
J'ai ajouté un 4ème cas de test qui nécessite un arrondi à 12,5, car les réponses utilisant un plancher entier auraient passé les 3 premiers cas de test.
Justin Mariner
1
À propos des langages qui ne disposent pas de capacités de traitement d'image comme C ++, est-il acceptable d'utiliser une bibliothèque? Dans l'affirmative, pour le nombre d'octets, doit-il compter uniquement le code écrit ou également la taille des fichiers DLL requis pour exécuter le programme?
HatsuPointerKun

Réponses:

10

Python 2 , 114 110 98 octets

-4 octets grâce à TheLethalCoder
-12 octets grâce à Ruud

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

Essayez-le en ligne!

Barre
la source
Utiliser à la 191place?
TheLethalCoder
2
J'allais suggérer x&y&z&192>191, mais la version mise à jour est tout aussi courte.
Arnauld
2
Pourriez - vous potentiellement remplacer import PIL.Image as Pavec from PIL.Image import*et enregistrer 1 octet lors d'un changement i=P.opende i=open? Je ne sais pas si cela causerait des problèmes car open est déjà une fonction définie, mais je ne peux pas tester car je n'ai pas la possibilité d'installer le module.
Arnold Palmer
1
Ouais, ça semble marcher. Enregistre 1 octet.
Arfie
2
@Rod votre code n'a pas à s'exécuter sur toutes les plates-formes - la langue est définie par l'interpréteur. S'il fonctionne pour vous, il est valide.
Tim
10

MATL , 18 17 octets

Yi191>3&A1eYm8*Yo

L'exemple fonctionne avec les quatre images fournies (désolé pour la qualité de l'aperçu; cliquez pour la pleine résolution):

entrez la description de l'image ici

Ou supprimez les quatre derniers caractères pour voir les résultats sans arrondir:

entrez la description de l'image ici

Explication

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
la source
Je me demande ce qui peut être fait avec les esolangs
Евгений Новиков
6

Java (OpenJDK 8) , 204 octets

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

Essayez-le en ligne! J'oublie toujours que TIO sort STDERR dans l'onglet de débogage. Peut-être qu'il pourrait aimer surligner en rouge en cas d'erreur?

Roman Gräf
la source
Peu de choses: votre code s'exécute actuellement dans une boucle infinie, car vous n'incrémentez jamais xou y. Vous avez attribué y=0deux fois, vous pouvez donc supprimer la première affectation. La classe Colordoit être entièrement qualifiée ( java.awt.Color) ou vous devez inclure l'importation dans votre nombre d'octets. Et votre code échoue pour le 4ème cas de test (retourne 0 au lieu de 1).
Justin Mariner
Je sais que cela fait un moment, mais vous pouvez jouer au golf sur 6 octets en supprimant les supports de la boucle for interne et en changeant le &&to &et ,y=0le ,y: Essayez-le en ligne.
Kevin Cruijssen
6

C #, 150 146 octets

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 octets enregistrés grâce à @Ian H.

Version complète / formatée:

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
la source
for(h=0 h<b.Height;++t)Je pense que vous avez manqué un point-virgule là-bas
Kritixi Lithos
2
Vous pouvez remplacer le /0.125par *8à la fin pour économiser quelques octets.
Ian H.
@Cowsquack J'avais supprimé le point-virgule au lieu de l'espace! Fixé maintenant ..
TheLethalCoder
3

C #, 313 octets

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

Évidemment plus long que mon autre réponse mais celui-ci utilise LockBitset unsafecode pour accéder directement à l'image en mémoire; en tant que tel, il est incroyablement rapide. Je pourrais probablement supprimer l'appel à UnlockBitsmais c'est plus correct avec ça là.

Version complète / formatée:

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
la source
3

PowerShell , 200 octets

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

Obtient l'entrée en $args[0]tant que chemin de fichier d'image complet, construit un New Bitmapobjet dans $a. Ce n'est que le nom de l'objet interne; il prend en charge JPG, PNG, etc.

Nous faisons ensuite une double boucle à travers le .heightpuis .widthl'image, en les touchant pixel. Nous retirons les R,G,Bvaleurs et choisir celles qui sont -greaterthanor equal à 192et assurez - vous que countest 3(c. -à- tous sont-ish blanc). Ce résultat booléen est ajouté dans notre accumulateur $i.

Nous divisons ensuite pour obtenir le pourcentage, le multiplions par 8pour obtenir le nombre d'octas, puis [int]pour obtenir uniquement une sortie entière. (Notez que cela effectue l'arrondi bancaire - si ce n'est pas autorisé, il faudra plusieurs octets supplémentaires pour changer la méthode d'arrondi.)

AdmBorkBork
la source
2

dc, 74 octets

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

L'entrée est considérée comme un fichier P3 ppm, avec tous les espaces comme des retours à la ligne. La sortie est vers STDOUT.

Essayez-le en ligne!

poi830
la source
2

JavaScript, 83 77 octets

-6 octets par 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)

Contributions

Image 1

Image n ° 2

Image n ° 3

Image # 4

Démo

Евгений Новиков
la source
1
Très belle solution. Une astuce pratique avec les fonctions fléchées ES6 consiste à tout mettre entre parenthèses, séparées par des virgules ( a=>(b,c,d)) au lieu de faire a=>{b;c;return d}ou a=>eval("b;c;d"). Cela fonctionne à moins que vous n'ayez une boucle quelconque, auquel cas vous feriez probablement mieux d'utiliser la evalméthode.
ETHproductions
2

C (POSIX), 103 octets

Suppose l'entrée en tant que fichier BMP sur 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
la source
2

Code machine x86, 34 octets

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

Ces octets de code définissent une fonction qui prend une entrée bitmap et renvoie une valeur entière indiquant ses octas. Comme en C , les tableaux (comme les bitmaps) sont représentés comme un pointeur vers le premier élément et une taille / longueur. Ainsi, cette fonction prend deux paramètres: le nombre total de pixels dans le bitmap (lignes × colonnes) et un pointeur sur le bitmap lui-même.

Ce code utilise une convention d'appel basée sur un registre personnalisé, où le pointeur bitmap est passé dans le ESIregistre et la taille bitmap est passée dans leECX registre. Le résultat (octas) est, comme d'habitude, retourné EAX.

Comme déjà indiqué ci-dessus, l'entrée est considérée comme un bitmap. Plus précisément, un format 32 bpp est utilisé, dans un format petit-boutien, mais le canal alpha (octet de poids fort) est ignoré. Cela simplifie beaucoup de choses, nous permettant simplement de parcourir chaque pixel et de vérifier sa valeur de couleur RVB 32 bits. Une optimisation intelligente est également utilisée ici. Au lieu d'isoler chaque composante de couleur et de vérifier si elle est> = 192, nous masquons simplement la valeur entière de 32 bits par 0xC0C0C0 et testons si le résultat est> = 0xC0C0C0. Ceci sera évalué à vrai pour toutes les couleurs "nuage" et faux à toutes les couleurs "ciel" (hors nuage). Eh bien, je pensais que c'était intelligent! :-) Il enregistre certainement un grand nombre d'octets.

Par conséquent, afin de tester ce code, vous devrez convertir les images d'entrée en bitmaps 32 bpp. Vous ne pouvez pas utiliser Windows Paint pour cela, car il prend en charge un maximum de 24 bits par pixel. Cependant, il existe un certain nombre d'autres solutions logicielles qui peuvent le faire, comme Adobe Photoshop. j'ai utilisé cet outil gratuit , qui convertit un PNG en BMP 32 bpp sous Windows, ce qui signifie que vous n'avez besoin que de convertir du JPEG au PNG (ce que Paint peut faire).

Les autres hypothèses que je pose sont éminemment raisonnables:

  • Le bitmap est supposé avoir une taille supérieure à 0 ( c'est -à- dire qu'il est supposé contenir au moins un pixel). C'est raisonnable car, quand le ciel est nul, nous avons des problèmes plus importants que la météorologie.
  • Le drapeau de direction (DF ) est supposé être clair afin que nous puissions itérer correctement à travers le bitmap en utilisant leLODSD instruction. C'est la même hypothèse faite par la plupart des conventions d'appel x86, donc cela semble juste. Si vous ne l'aimez pas, ajoutez 1 octet au nombre d'une CLDinstruction.
  • Le mode d'arrondi du FPU x87 est supposé être réglé sur arrondi au plus proche pair. Cela garantit que nous obtenons le comportement correct lorsque nous convertissons le nombre d'octas d'un nombre à virgule flottante en résultat entier final, comme vérifié par le cas de test # 4. Cette hypothèse est raisonnable car il s'agit de l'état par défaut pour le FPU et il doit être conservé même en code C (où la troncature est le comportement d'arrondi par défaut, forçant les compilateurs qui souhaitent être conformes aux normes à générer du code inefficace qui modifie l'arrondi , effectue la conversion, puis modifie le mode d'arrondi).

Mnémoniques d'assemblage non golfés:

; 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

Vous n'avez sûrement pas fait tout ce chemin et vous vous demandez toujours comment fonctionne le code? :-)
Eh bien, c'est assez simple. Nous parcourons simplement le bitmap une valeur 32 bits à la fois, en vérifiant si cette valeur RVB de pixel est "nuageuse" ou "non nuageuse". S'il fait nuageux, nous incrémentons notre compteur pré-mis à zéro. À la fin, nous calculons: pixels nuageuxpixels totaux  × 8
(ce qui équivaut à: pixels nuageuxpixels totaux  ÷ 0,125).

Je ne peux pas inclure de lien TIO pour cela en raison du besoin d'images d'entrée. Je peux cependant vous fournir le harnais que j'ai utilisé pour tester cela sur 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;
}

Soyez prudent avec cela, cependant! Comme défini ci-dessus, ComputeOktasutilise une convention d'appel personnalisée, qu'un compilateur C ne respectera pas. Vous devez ajouter du code en haut de la procédure du langage assembleur pour charger les valeurs de la pile dans les registres attendus, par exemple :

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

JavaScript (ES6), 218 octets

(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

Prend un Imageobjet en entrée, qui peut être créé à partir d'un <image>élément.

Testez-le ici sur CodePen!

Alternative

Si l'entrée peut être considérée comme un tableau plat de valeurs RGBA, avec des dimensions: 82 octets

(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

Ce format d'entrée est très similaire à ce que cette réponse sur meta suggère.

Justin Mariner
la source
1

Mathematica 89 octets

Ce qui suit binarise l'image et détermine la fraction des nuages, c'est-à-dire les pixels blancs. Ensuite, il détermine combien de fois 0,125 s'inscrit dans le résultat. Il renvoie le plancher de cette valeur.

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