Wie bewölkt ist es?


22

Herausforderung

Bei einem bestimmten Bild des Himmels müssen Sie die Wolkendecke in Oktas ausgeben. Das gelieferte Bild ist eine Bilddatei (der Typ liegt bei Ihnen) und die Ausgabe sollte auf STDOUT erfolgen.

Oktas

In der Meteorologie ist eine Okta eine Maßeinheit, mit der die Menge der Wolkendecke an einem bestimmten Ort, z. B. einer Wetterstation, beschrieben wird. Die Himmelverhältnisse werden anhand der Anzahl der bewölkten Achtel des Himmels geschätzt, die von 0 Oktas (vollständig klarer Himmel) bis zu 8 Oktas (vollständig bedeckt) reichen.

Der Himmel wird immer ein Bild von ungefähr Mittag sein (also blauer Himmel, nicht Rot / Nachthimmel).

Die Farbe einer Wolke ist immer eine Farbe, die dem folgenden Muster folgt:

#ABCDEF

Wo AB >= C0, CD >= C0und EF >= C0.

Oder in RGB:

(A, B, C)

Wo A >= 192, B >= 192und C >= 192.

Hier sind die prozentualen Bedeckungen in Bezug auf die 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

Die Prozentsätze sind der Prozentsatz des Bildes, bei dem es sich um eine Wolke handelt.

Wenn die prozentuale Wolke Ihres Bildes nicht ein Vielfaches von 12,5 ist, sollten Sie auf die nächste runden.

Ausgabe

Die Ausgabe sollte nur die Oktanummer sein (Sie müssen die Einheit nicht sagen).

Beispiele

1 Okta (18.030743615677714% Wolke)

0 Oktas (0,0% Wolke)

3 Oktas (42.66319444444445% Wolke)

1 Okta (12.000401814778645% Wolke)

Python-Code zur Berechnung von Zahlen

Gewinnen

Kürzester Code in Bytes gewinnt.


Ist das nicht der letzte 3 Oktas?
TheLethalCoder

@TheLethalCoder Whoops, bearbeitet
Beta Decay

Gibt es ein Maximum für die Abmessungen eines Bildes?
Shaggy

2
Ich habe einen vierten Testfall hinzugefügt, der auf 12,5 gerundet werden muss, da Antworten mit ganzzahligem Boden die ersten drei Testfälle bestanden hätten.
Justin Mariner

1
Ist es in Ordnung, eine Bibliothek für Sprachen zu verwenden, die keine Bildverarbeitungsfunktionen wie C ++ besitzen? Wenn ja, sollte es für die Byteanzahl nur den geschriebenen Code oder auch die Größe der DLL-Dateien zählen, die zum Ausführen des Programms erforderlich sind?
HatsuPointerKun

Antworten:


10

Python 2 , 114 110 98 Bytes

-4 Bytes dank TheLethalCoder
-12 Bytes dank Ruud

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

Probieren Sie es online!


Verwenden Sie 191stattdessen?
TheLethalCoder

2
Ich wollte vorschlagen x&y&z&192>191, aber die aktualisierte Version ist genauso kurz.
Arnauld

2
Könnten Sie möglicherweise ersetzen import PIL.Image as Pmit from PIL.Image import*1 Byte und sparen beim Wechsel i=P.openzu i=open? Ich weiß nicht, ob dies zu Problemen führen würde, da open bereits eine definierte Funktion ist, aber ich kann es nicht testen, da ich nicht in der Lage bin, das Modul zu installieren.
Arnold Palmer

1
Ja, das scheint zu funktionieren. Spart 1 Byte.
Arfie

2
@Rod Ihr Code muss nicht auf allen Plattformen ausgeführt werden - die Sprache wird vom Interpreter festgelegt. Wenn es für Sie läuft, dann ist es gültig.
Tim

10

MATL , 18 17 Bytes

Yi191>3&A1eYm8*Yo

Das Beispiel wird mit den vier bereitgestellten Bildern ausgeführt.

Bildbeschreibung hier eingeben

Oder entfernen Sie die letzten vier Zeichen, um die Ergebnisse ohne Rundung anzuzeigen:

Bildbeschreibung hier eingeben

Erläuterung

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

Ich frage mich, was mit Esolangs getan werden kann
Евгений Новиков

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

Probieren Sie es online! Ich vergesse immer, dass TIO STDERR an die Debug-Registerkarte ausgibt. Vielleicht könnte es im Fehlerfall rot hervorgehoben werden?


Einige Dinge: Ihr Code wird derzeit in einer Endlosschleife ausgeführt, da Sie xoder nie erhöhen y. Sie haben y=0zweimal zugewiesen , sodass Sie die erste Zuweisung entfernen können. Die Klasse Colormuss entweder vollständig qualifiziert sein ( java.awt.Color) oder Sie müssen den Import in Ihre Byteanzahl aufnehmen. Und Ihr Code schlägt für den 4. Testfall fehl (gibt 0 statt 1 zurück).
Justin Mariner

Ich weiß, es ist schon eine Weile her, aber Sie können 6 Bytes Golf spielen, indem Sie die Klammern der inneren for-Schleife entfernen und das &&to &und ,y=0to ändern ,y: Versuchen Sie es online.
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);}

4 Bytes gespart dank @Ian H.

Voll / Formatierte Version:

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)Ich glaube, Sie haben dort ein
Semikolon

2
Sie können das Ersetzen /0.125mit *8am Ende ein paar Bytes zu speichern.
Ian H.

@Cowsquack Ich habe das Semikolon anstelle des Leerzeichens gelöscht!
Behoben

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

Offensichtlich länger als meine andere Antwort, aber diese verwendet LockBitsund unsafeCode, um direkt auf das Bild im Speicher zuzugreifen. als solches ist es unglaublich schnell. Ich könnte den Anruf wahrscheinlich entfernen, UnlockBitsaber es ist damit dort korrekter.

Voll / Formatierte Version:

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)

Ruft die Eingabe $args[0]als vollständiger Bilddateipfad ab und erstellt ein New BitmapObjekt in $a. Dies ist nur der interne Objektname. es unterstützt JPG, PNG, etc.

Wir durchlaufen dann das .heightund dann .widthdas Bild in einer Doppelschleife und berühren jedes Bild pixel. Wir ziehen die R,G,BWerte heraus und wählen dann diejenigen aus, die -gwiederhergestellt werden als oder qualifiziert sind e, 192und stellen sicher, dass dies der Fall countist 3(dh alle sind weißlich). Dieses boolesche Ergebnis wird in unseren Akkumulator addiert $i.

Wir teilen dann auf, um den Prozentsatz zu erhalten, multiplizieren ihn mit 8, um die Anzahl der Oktas zu erhalten, und erhalten dann [int]nur eine ganzzahlige Ausgabe. (Beachten Sie, dass hierdurch die Bankerrundung ausgeführt wird. Wenn dies nicht zulässig ist, müssen Sie die Rundungsmethode um einige Bytes verlängern.)


2

Gleichstrom, 74 Bytes

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

Die Eingabe erfolgt als P3-ppm-Datei, wobei alle Leerzeichen als Zeilenumbrüche verwendet werden. Die Ausgabe erfolgt nach STDOUT.

Probieren Sie es online!


2

JavaScript, 83 Bytes

-6 Bytes von 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)

Eingänge

Bild 1

Bild 2

Bild 3

Bild 4

Demo


1
Sehr schöne Lösung. Ein praktischer Trick mit ES6-Pfeilfunktionen besteht darin, alles in Klammern zu setzen, die durch Kommas ( a=>(b,c,d)) getrennt sind, anstatt a=>{b;c;return d}oder zu tun a=>eval("b;c;d"). Dies funktioniert nur, wenn Sie eine Schleife haben. In diesem Fall sollten Sie die evalMethode am besten anwenden.
ETHproductions

2

C (POSIX), 103 Bytes

Übernimmt die Eingabe als BMP-Datei auf 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

x86-Maschinencode, 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

Diese Codebytes definieren eine Funktion, die eine Bitmap-Eingabe annimmt und einen ganzzahligen Wert zurückgibt, der die Oktas angibt. Wie in C werden Arrays (wie Bitmaps) als Zeiger auf das erste Element und als Größe / Länge dargestellt. Daher akzeptiert diese Funktion zwei Parameter: die Gesamtzahl der Pixel in der Bitmap (Zeilen × Spalten) und einen Zeiger auf die Bitmap selbst.

Dieser Code verwendet eine benutzerdefinierte, auf Registern basierende Aufrufkonvention, bei der der Bitmap-Zeiger im ESIRegister und die Bitmap-Größe im ECXRegister übergeben werden. Das Ergebnis (Oktas) wird wie üblich in zurückgegeben EAX.

Wie oben bereits erwähnt, wird die Eingabe als Bitmap verwendet. Insbesondere wird ein 32-bpp-Format in einem Little-Endian-Format verwendet, aber der Alphakanal (Byte höchster Ordnung) wird ignoriert. Dies vereinfacht eine Menge Dinge und ermöglicht es uns, einfach durch jedes Pixel zu iterieren und seinen 32-Bit-RGB-Farbwert zu überprüfen. Auch hier kommt eine clevere Optimierung zum Einsatz. Anstatt jede Farbkomponente zu isolieren und zu prüfen, ob sie> = 192 ist, maskieren wir einfach den gesamten 32-Bit-Wert mit 0xC0C0C0 und testen, ob das Ergebnis> = 0xC0C0C0 ist. Dies wird für alle "Wolken" -Farben als wahr und für alle "Himmel" -Farben (keine Wolken) als falsch bewertet. Nun, ich fand es klug! :-) Es spart sicherlich eine große Anzahl von Bytes.

Um diesen Code zu testen, müssen Sie die Eingabebilder daher in Bitmaps mit 32 Bit / s konvertieren. Sie können Windows Paint hierfür nicht verwenden, da es maximal 24 Bit pro Pixel unterstützt. Es gibt jedoch eine Reihe anderer Softwarelösungen, die dies unterstützen, beispielsweise Adobe Photoshop. Ich habe dieses kostenlose Tool verwendet , das ein PNG in ein 32-bpp-BMP unter Windows konvertiert, was bedeutet, dass Sie nur von JPEG in PNG konvertieren müssen (was Paint kann).

Andere Annahmen, die ich setze, sind ausgesprochen vernünftig:

  • Es wird angenommen, dass die Bitmap eine Größe größer als 0 hat ( d. H , es wird angenommen, dass sie mindestens ein Pixel enthält). Das ist vernünftig, denn wenn der Himmel null ist, haben wir größere Probleme als die Meteorologie.
  • Es DFwird angenommen, dass das Richtungsflag ( ) klar ist, damit wir die Bitmap unter Verwendung der LODSDAnweisung korrekt durchlaufen . Dies ist die gleiche Annahme wie bei den meisten x86-Aufrufkonventionen. Wenn es Ihnen nicht gefällt, addieren Sie 1 Byte zur Anzahl für eine CLDAnweisung.
  • Es wird davon ausgegangen, dass der Rundungsmodus für die x87-FPU auf die geraden Werte gerundet wird. Dies stellt sicher, dass wir das richtige Verhalten erhalten, wenn wir die Anzahl der Oktas von einem temporären Gleitkommawert in das endgültige ganzzahlige Ergebnis konvertieren, wie im Testfall Nr. 4 verifiziert. Diese Annahme ist vernünftig, da dies der Standardstatus für die FPU ist und er auch im C-Code beibehalten werden muss (wobei das Standardrundungsverhalten das Abschneiden ist), wodurch Compiler, die normenkonform sein möchten, gezwungen werden, ineffizienten Code zu generieren, der die Rundung ändert führt die Konvertierung durch und ändert dann den Rundungsmodus zurück).

Ungolfed Assembler-Mnemonik:

; 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

Sicherlich haben Sie es nicht so weit gebracht und fragen sich immer noch, wie der Code funktioniert? :-)
Nun, es ist ziemlich einfach. Wir durchlaufen die Bitmap nur jeweils um einen 32-Bit-Wert und prüfen, ob dieser Pixel-RGB-Wert "wolkig" oder "nicht wolkig" ist. Wenn es bewölkt ist, erhöhen wir unseren Zähler vor dem Nullsetzen. Am Ende berechnen wir: Bewölkte PixelGesamtpixel  × 8
(was äquivalent ist zu: Bewölkte PixelGesamtpixel  ÷ 0,125).

Ich kann hierfür keinen TIO-Link einfügen, da Eingabebilder erforderlich sind. Ich kann Ihnen jedoch das Kabel zur Verfügung stellen, mit dem ich dies unter Windows getestet habe:

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

Aber sei vorsichtig damit! ComputeOktasVerwendet wie oben definiert eine benutzerdefinierte Aufrufkonvention, die von einem C-Compiler nicht beachtet wird. Sie müssen Code oben in der Assemblersprachenprozedur hinzufügen, um Werte aus dem Stapel in die erwarteten Register zu laden, z .

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

Nimmt ein ImageObjekt als Eingabe, das aus einem <image>Element erstellt werden kann.

Testen Sie es hier auf CodePen!

Alternative

Wenn die Eingabe als ein flaches Array von RGBA-Werten mit folgenden Abmessungen erfolgen kann: 82 Byte verwendet werden kann

(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

Dieses Eingabeformat ist dem sehr ähnlich, was diese Antwort auf Meta vorschlägt.


1

Mathematica 89 Bytes

Das folgende Beispiel digitalisiert das Bild und bestimmt den Anteil der Wolken, dh der weißen Pixel. Dann wird bestimmt, wie oft .125 in das Ergebnis passt. Es wird der Floor dieses Wertes zurückgegeben.

o@i_:=⌊8Tr@Flatten[ImageData@MorphologicalBinarize[i,.932],1]/Times@@ImageDimensions@i⌋
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.