Quanto è nuvoloso?


22

Sfida

Data un'immagine del cielo, è necessario produrre la copertura nuvolosa in oktas. L'immagine fornita sarà un file di immagine (il tipo dipende da te) e l'output dovrebbe essere su STDOUT.

ottavi

In meteorologia, un okta è un'unità di misura utilizzata per descrivere la quantità di copertura nuvolosa in un dato luogo come una stazione meteorologica. Le condizioni del cielo sono stimate in termini di quanti ottavi di cielo sono coperti da nuvole, che vanno da 0 okta (cielo completamente chiaro) a 8 okta (completamente nuvoloso).

Il cielo sarà sempre un'immagine intorno a mezzogiorno (quindi, cielo blu, non rosso / cielo notturno).

Il colore di una nuvola sarà sempre un colore che segue il seguente schema:

#ABCDEF

Dove AB >= C0, CD >= C0e EF >= C0.

Oppure, in RGB:

(A, B, C)

Dove A >= 192, B >= 192e C >= 192.

Ecco le percentuali di copertura relative agli 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

Le percentuali sono la percentuale dell'immagine che è nuvola.

Se la nuvola percentuale della tua immagine non è un multiplo di 12,5, dovresti arrotondare al più vicino.

Produzione

L'output dovrebbe essere solo il numero okta (non devi dire l'unità).

Esempi

1 okta (18.030743615677714% nuvola)

0 okta (0,0% nuvola)

3 oktas (42.66319444444445% cloud)

1 okta (12.000401814778645% cloud)

Codice Python utilizzato per calcolare i numeri

vincente

Vince il codice più breve in byte.


L'ultimo non è 3 okta?
TheLethalCoder

@TheLethalCoder Whoops, modificato
Decadimento beta

C'è un massimo per le dimensioni di un'immagine?
Shaggy,

2
Ho aggiunto un quarto caso di test che richiede l'arrotondamento fino a 12,5, poiché le risposte utilizzando la pavimentazione intera avrebbero superato i primi 3 casi di test.
Justin Mariner,

1
A proposito di lingue che non dispongono di funzionalità di elaborazione delle immagini come C ++, è corretto utilizzare una libreria? In tal caso, per il conteggio dei byte, dovrebbe contare solo il codice scritto o anche la dimensione dei file DLL richiesti per eseguire il programma?
HatsuPointerKun

Risposte:


10

Python 2 , 114 110 98 byte

-4 byte grazie a TheLethalCoder
-12 byte grazie a Ruud

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

Provalo online!


Usare 191invece?
TheLethalCoder

2
Stavo per suggerire x&y&z&192>191, ma la versione aggiornata è altrettanto breve.
Arnauld,

2
Potresti potenzialmente sostituire import PIL.Image as Pcon from PIL.Image import*e salvare 1 byte quando cambi i=P.openin i=open? Non so se ciò causerebbe problemi poiché open è già una funzione definita, ma non posso testare poiché non ho la possibilità di installare il modulo.
Arnold Palmer,

1
Sì, sembra funzionare. Salva 1 byte.
Arfie,

2
@Rod il tuo codice non deve essere eseguito su tutte le piattaforme - la lingua è definita dall'interprete. Se funziona per te, allora è valido.
Tim

10

MATL , 18 17 byte

Yi191>3&A1eYm8*Yo

L'esempio viene eseguito con le quattro immagini fornite (scusate la qualità dell'anteprima; fate clic per la risoluzione completa):

inserisci qui la descrizione dell'immagine

Oppure rimuovi gli ultimi quattro caratteri per vedere i risultati senza arrotondare:

inserisci qui la descrizione dell'immagine

Spiegazione

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

Mi chiedo cosa si possa fare usando 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;}

Provalo online! Dimentico sempre che TIO genera STDERR nella scheda di debug. Forse potrebbe evidenziare il rosso in caso di errore?


Poche cose: il tuo codice attualmente viene eseguito in un ciclo infinito, dal momento che non si incrementa mai xo y. Hai assegnato y=0due volte, quindi puoi rimuovere il primo incarico. La classe Colordeve essere completamente qualificata ( java.awt.Color) oppure è necessario includere l'importazione nel conteggio dei byte. E il tuo codice fallisce per il 4o caso di test (restituisce 0 invece di 1).
Justin Mariner,

So che è stato un po ', ma si può golf 6 byte rimuovendo le staffe di interno per-loop, e cambiando il &&verso &e ,y=0per ,y: Provalo in rete.
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);}

4 byte salvati grazie a @Ian H.

Versione completa / formattata:

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)Penso che ti sia mancato un punto e virgola lì
Kritixi Lithos,

2
È possibile sostituire il /0.125con *8alla fine per salvare alcuni byte.
Ian H.

@Cowsquack Avevo eliminato il punto e virgola anziché lo spazio! Risolto ora ..
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);}}}

Ovviamente più lungo dell'altra mia risposta ma questa usa LockBitse unsafecodice per accedere direttamente all'immagine in memoria; come tale è incredibilmente veloce. Probabilmente potrei rimuovere la chiamata a UnlockBitsma è più corretto con essa lì.

Versione completa / formattata:

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)

Ottiene l'input $args[0]come percorso del file di immagine completo, crea un New Bitmapoggetto $a. Questo è solo il nome dell'oggetto interno; supporta JPG, PNG, ecc.

Quindi eseguiamo un doppio ciclo attraverso l'immagine .heighte poi .widthl'immagine, toccandone ciascuna pixel. Tiriamo fuori i R,G,Bvalori e quindi selezionare quelli che sono -greaterthanor equal per 192e assicurarsi che countsia 3(vale a dire, tutti sono bianco-ish). Quel risultato booleano viene aggiunto al nostro accumulatore $i.

Quindi dividiamo per ottenere la percentuale, la moltiplichiamo 8per ottenere il numero di okta e quindi [int]per ottenere solo un output intero. (Si noti che questo esegue l'arrotondamento del banco - se ciò non è consentito, saranno necessari diversi byte per modificare il metodo di arrotondamento.)


2

dc, 74 byte

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

L'input è preso come un file ppm P3, con tutti gli spazi bianchi come newline. L'uscita è su STDOUT.

Provalo online!


2

JavaScript, 83 77 byte

-6 byte per 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)

ingressi

Immagine n. 1

Immagine n. 2

Immagine n. 3

Immagine n. 4

dimostrazione


1
Soluzione molto bella. Un trucco pratico con le funzioni freccia ES6 è avvolgere tutto tra parentesi, separato da virgole ( a=>(b,c,d)) invece di fare a=>{b;c;return d}o a=>eval("b;c;d"). Funziona a meno che tu non abbia un ciclo di qualche tipo, nel qual caso probabilmente ti conviene usare il evalmetodo.
ETHproductions

2

C (POSIX), 103 byte

Presuppone l'input come file BMP su 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

Codice macchina 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

Questi byte di codice definiscono una funzione che accetta un input bitmap e restituisce un valore intero che indica i suoi okta. Come in C , le matrici (come le bitmap) sono rappresentate come puntatore al primo elemento e dimensioni / lunghezza. Pertanto, questa funzione accetta due parametri: il numero totale di pixel nella bitmap (righe × colonne) e un puntatore alla bitmap stessa.

Questo codice utilizza una convenzione di chiamata basata su registro personalizzata, in cui il puntatore bitmap viene passato nel ESIregistro e la dimensione bitmap viene passata nel ECXregistro. Il risultato (oktas) è, come al solito, restituito EAX.

Come già detto sopra, l'input è preso come bitmap. In particolare, viene utilizzato un formato a 32 bpp, in un formato little-endian, ma il canale alfa (byte di ordine più elevato) viene ignorato. Questo semplifica molte cose, permettendoci di scorrere semplicemente ogni pixel e controllare il suo valore di colore RGB a 32 bit. Qui viene anche utilizzata un'ottimizzazione intelligente. Invece di isolare ciascun componente colore e verificare se è> = 192, mascheriamo l'intero valore a 32 bit di 0xC0C0C0 e testiamo se il risultato è> = 0xC0C0C0. Ciò verrà valutato come vero per tutti i colori "nuvola" e falso per tutti i colori "cielo" (non nuvola). Beh, ho pensato che fosse intelligente! :-) Salva sicuramente un gran numero di byte.

Pertanto, per testare questo codice, dovrai convertire le immagini di input in bitmap a 32 bpp. Non è possibile utilizzare Windows Paint per questo, perché supporta un massimo di 24 bit per pixel. Tuttavia, ci sono diverse altre soluzioni software che possono farlo, come Adobe Photoshop. Ho usato questo strumento gratuito , che converte un PNG in un BMP a 32 bpp su Windows, il che significa che devi solo convertire da JPEG a PNG (cosa che Paint può fare).

Altre ipotesi che io sostengo sono eminentemente ragionevoli:

  • Si presume che la bitmap abbia una dimensione maggiore di 0 ( ovvero , si presume che contenga almeno un pixel). Questo è ragionevole perché, quando il loro cielo è nullo, abbiamo problemi più grandi della meteorologia.
  • Si DFpresume che il flag di direzione ( ) sia chiaro in modo da iterare correttamente attraverso la bitmap usando l' LODSDistruzione. Questo è lo stesso presupposto fatto dalla maggior parte delle convenzioni di chiamata x86, quindi sembra giusto. Se non ti piace, aggiungi 1 byte al conteggio per CLDun'istruzione.
  • Si presume che la modalità di arrotondamento per FPU x87 sia impostata su arrotondamento al più vicino-pari. Questo assicura che otteniamo il comportamento corretto quando convertiamo il numero di okta da un temporaneo in virgola mobile al risultato intero finale, come verificato dal test case n. 4. Questo presupposto è ragionevole perché questo è lo stato predefinito per la FPU e deve essere mantenuto anche nel codice C (dove il troncamento è il comportamento di arrotondamento predefinito, costringendo i compilatori che desiderano essere conformi agli standard per generare codice inefficiente che modifica l'arrotondamento modalità, esegue la conversione, quindi modifica la modalità di arrotondamento indietro).

Mnemonici di assemblaggio non golfati:

; 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

Sicuramente non l'hai fatto fino in fondo e ti stai ancora chiedendo come funziona il codice? :-)
Beh, è ​​abbastanza semplice. Esaminiamo semplicemente la bitmap un valore a 32 bit alla volta, verificando se quel valore di pixel RGB è "nuvoloso" o "non nuvoloso". Se è nuvoloso, incrementiamo il nostro contatore pre-azzerato. Alla fine, calcoliamo: pixel nuvolosipixel totali  × 8
(che equivale a: pixel nuvolosipixel totali  ÷ 0,125).

Non posso includere un collegamento TIO per questo a causa della necessità di immagini di input. Posso, tuttavia, fornirti il ​​cablaggio che ho usato per testarlo su 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;
}

Stai attento con questo, però! Come definito sopra, ComputeOktasutilizza una convenzione di chiamata personalizzata, che un compilatore C non rispetterà. È necessario aggiungere il codice nella parte superiore della procedura del linguaggio assembly per caricare i valori dallo stack nei registri previsti, ad es :

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

Prende un Image oggetto come input, che può essere creato da un <image>elemento.

Provalo qui su CodePen!

Alternativa

Se l'input può essere preso come array piatto di valori RGBA, con dimensioni: 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

Questo formato di input è molto simile a quello che suggerisce questa risposta su meta .


1

Mathematica 89 byte

Di seguito binarizza l'immagine e determina la frazione di nuvole, ovvero i pixel bianchi. Quindi determina quante volte .125 si adatta al risultato. Restituisce il piano di quel valore.

o@i_:=⌊8Tr@Flatten[ImageData@MorphologicalBinarize[i,.932],1]/Times@@ImageDimensions@i⌋
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.