xkcd challenge : "[x] 색상 인 화면 비율"


57

그래서 우리 모두이 xkcd 만화를 본 것 같습니다.

http://imgs.xkcd.com/comics/self_description.png:

이것은 너무 일반적이거나 너무 어려울 수 있습니다. 그러나 도전 과제는 최소한 2 가지 색상을 가진 창을 만들고 영어로 각 색상의 화면 비율을 표시하는 모든 언어의 프로그램을 만드는 것입니다.

전의. 가장 간단한 해결책은 "검은 색이 이미지의 백분율 : [x] %."라는 검은 색 글자가있는 흰색 배경입니다.

당신이 원하는만큼 미쳤거나 단순하게 갈 수 있습니다. 일반 텍스트는 유효한 솔루션이지만 xkcd 만화와 같이 재미있는 이미지를 만드는 것이 훨씬 좋습니다! 우승자는 가장 많은 표를 얻는 가장 재미 있고 창의적인 솔루션이됩니다. xkcd에 재미 있고 가치있는 무언가를 만드십시오! :)

그래서 당신은 어떻게 생각하십니까? 재미있는 도전처럼 들리십니까? :)

답변에서 실행중인 프로그램의 스크린 샷을 포함하십시오 :)


6
"이 프로그램에는 64 개의 A, 4 개의 B, 그리고 34 개의 큰 따옴표가 있습니다"프로그램이 더 흥미로울 것입니다 :-)
John Dvorak

2
좋아 ... 객관적인 승리 기준은 무엇입니까? 특정 출력이 유효한지 어떻게 확인합니까? 그것이 사실이며 그것 자체의 특성을 수치 적으로 묘사하는 것으로 충분합니까?
John Dvorak

@ JanDvorak 오, 그거 좋은 거에요! 알파벳 프로그램은 실제로 이것을 원래 생각한 것이지만 소스 코드 요소를 추가하는 것을 고려하지 않았습니다! 당신은 그것을 질문으로 게시해야합니다 :) 그렇습니다. 충분하며 자체를 설명하는 것으로 충분합니다. 흠, 당신 말이 맞아요, 나는 최종 결과가 옳았다는 것을 어떻게 증명할 것인지에 대해서는 생각하지 않았습니다. 결과 이미지에서 각 색상의 모든 픽셀을 계산하는 방법이 필요하다고 생각합니다. 이제 조사하겠습니다. (죄송 합니다만 첫 번째 질문에 문제가있었습니다 ... 시도했지만 이번에 처음입니다! 감사합니다 :))
WendiKidd

truthiness과 자기 참조가 충분한 기준이있는 경우, 여기 내 golfscript 참가자의 : "/.*/"(읽기 : [소스 코드] 개행 문자를 포함하지 않음)
존 드보락

@ JanDvorak 흠, 나는 여기에 코드를 시도 하고 출력은 따옴표없이 코드와 동일했습니다. 어쩌면 나는 이것을 올바르게 설명하고 있지 않을 수도 있습니다. 미안합니다. 최소한 2 개의 색상이 생성되어야하며 영어 문장의 일부 형태로 출력에서 ​​각 색상이 차지하는 화면 비율을 나타내는 실제 단어를 생성해야합니다. 어리석은 생각이었을 것입니다. 나는 그것이 재미있을 것이라고 생각했지만 실제로는 작동하지 않을 수 있습니다 :)
WendiKidd

답변:


35

느릅 나무

아직이 허점을 사용하는 사람을 보지 못했습니다 : 데모

import Color exposing (hsl)
import Graphics.Element exposing (..)
import Mouse
import Text
import Window

msg a = centered <| Text.color a (Text.fromString "half the screen is this color")

type Pos = Upper | Lower

screen (w,h) (x,y) = 
  let (dx,dy) = (toFloat x - toFloat w / 2, toFloat h / 2 - toFloat y)
      ang = hsl (atan2 dy dx) 0.7 0.5
      ang' = hsl (atan2 dx dy) 0.7 0.5
      box c = case c of
        Upper -> container w (h // 2) middle (msg ang) |> color ang'
        Lower -> container w (h // 2) middle (msg ang') |> color ang
  in  flow down [box Upper, box Lower]

main = Signal.map2 screen Window.dimensions Mouse.position

여기에 이미지 설명을 입력하십시오


3
큰 허점!
Timtech

나는 이것을 사랑한다 !!! 적어도 지금은 투명한 영리한 점에 대한 확인 표시가 나타납니다. 그것을 사랑하십시오!
WendiKidd

13
가장 좋은 점은 여전히 ​​어떤 문장이 어떤 색인지 이야기하고 있는지 잘 모르겠습니다.
Brilliand

3
이것은 view sourceshare-elm.com에 의해 작성되었으며 컴파일 된 JS / HTML의 일부가 아닙니다.
hoosierEE

1
@ML "this"라는 단어의 범위에 따라 다릅니다. 자바 스크립트 프로그래머 이해 ...
hoosierEE

37

HTML이 포함 된 JavaScript

오리지널 만화를보다 정확하게 재현하려고했습니다. html2canvas 라이브러리를 사용하여 스크린 샷을 만듭니다. 숫자는 반복적으로 계산되므로 창의 크기를 조정하거나 페이지에 무언가를 실시간으로 추가 할 수도 있습니다.

온라인으로 사용해보십시오 : http://copy.sh/xkcd-688.html

스크린 샷은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

<html contenteditable>
<script src=http://html2canvas.hertzen.com/build/html2canvas.js></script>
<script>
onload = function() {
    setInterval(k, 750);
    k();
}
function k() {
    html2canvas(document.body, { onrendered: t });
}
function t(c) {
    z.getContext("2d").drawImage(c, 0, 0, 300, 150);
    c = c.getContext("2d").getImageData(0, 0, c.width, c.height).data;

    for(i = y = 0; i < c.length;) 
        y += c[i++];

    y /= c.length * 255;

    x.textContent = (y * 100).toFixed(6) + "% of this website is white";

    q = g.getContext("2d");

    q.fillStyle = "#eee";
    q.beginPath();
    q.moveTo(75, 75);
    q.arc(75,75,75,0,7,false);
    q.lineTo(75,75);
    q.fill();

    q.fillStyle = "#000";
    q.beginPath();
    q.moveTo(75, 75);
    q.arc(75,75,75,0,6.28319*(1-y),false);
    q.lineTo(75,75);
    q.fill();
}
</script>
<center>
<h2 id=x></h2>
<hr>
<table><tr>
<td>Fraction of<br>this website<br>which is white _/
<td><canvas width=150 id=g></canvas>
<td>&nbsp; Fraction of<br>- this website<br>&nbsp; which is black
</table>
<hr>
0
<canvas style="border-width: 0 0 1px 1px; border-style: solid" id=z></canvas>
<h4>Location of coloured pixels in this website</h4>

좋은!! xkcd 만화와의 유사점과 텍스트를 변경할 수 있다는 사실을 좋아하십시오. 산뜻한! : D
WendiKidd

1
인상적인 작품 oO
izabera

근사하지만 ... "솔루션"이 되려면 안정화되어야한다고 생각합니다. 완전히 생각하지는 못했지만 제한된 숫자 글리프 세트에서 그릴 때 임의의 정밀도에 대한 솔루션이 반드시 필요한 것은 아니므로 높은 정밀도로 해결할 수 없으면 정밀도를 취소해야합니다 당신은 노력하고 있습니다. 흑백 픽셀을 미리 계산하는 모노 스페이스 글꼴을 사용해야한다고 생각합니다.
Dr. Rebmu

3 가지 색상을 사용하고 있으므로 회색의 백분율은 어디에 있습니까? ;)
ML

26

처리, 222 자

http://i.imgur.com/eQzMGzk.png

나는 항상 그 코믹 스트립의 내 자신의 버전을 만들고 싶었습니다! 내가 할 수있는 가장 간단한 (유일한) 방법은 시행 착오였습니다. 무언가를 그려서 세고 다시 그려보십시오 ...

이 프로그램은 몇 초 후에 정확한 비율로 정산됩니다. 별로 예쁘지는 않지만 대화식입니다 . 창의 크기를 조정하면 다시 계산되기 시작합니다.

가독성을위한 몇 가지 줄 바꿈이 추가되었습니다.

float s,S,n;
int i;
void draw(){
frame.setResizable(true);
background(255);
fill(s=i=0);
text(String.format("%.2f%% of this is white",S/++n*100),10,10);
loadPixels();
while(i<width*height)if(pixels[i++]==-1)s++;
S+=s/height/width;
}

흰색 픽셀의 백분율 만 표시합니다. 텍스트의 앤티 앨리어싱으로 인해 흰색이 아닌 픽셀이 반드시 검은 색일 필요는 없습니다. 실행 시간이 길수록 크기 조정시 자체 업데이트에 더 많은 시간이 필요합니다.

편집하다:

따라서 코드 도전입니다. 어쨌든 나는 골프를 쳤다. 나중에 일종의 그래프를 추가 할 수도 있지만 일반적인 원칙은 동일하게 유지됩니다. 상호 작용은 내가 생각하는 깔끔한 부분입니다.


아주 좋아요 !! 나는 당신이 상호 작용에 대한 추가적인 신용을 얻는다고 생각합니다. 나는 창 크기를 재조정하는 것이 재미 있었다! 매우 시원합니다 :) 그리고 당신은 나의 첫 반응입니다! 누구든지 놀아 줄지 몰랐어요. 고마워요. 당신은 내 하루를 만들었습니다. : D +1! (하지만 궁금하지만 시간이 지남에 따라 속도가 느려지고 정확한 비율에 가까워지는 이유는 무엇입니까? 나는 무슨 일이 일어나고 있는지 궁금합니다. 전에는이 언어를 본 적이 없습니다. 이 사이트 주위에 많은 새로운 물건 파고!)
WendiKidd

headdesk 실수로 +1을 클릭하는 것을 잊어 버렸습니다. 이제 +1 ... 하하. 죄송합니다!
WendiKidd

1
대화 형 기능을 추가하기 위해 사용자가 마우스로 그릴 수있는 다른 기능을 추가 할 수 있습니다.
AJMansfield

7
거룩한 상자 그림자, 배트맨
보장 글스

당신이 골프를 원한다면 background(-1)대신에 사용할 수 있습니다background(255)
Kritixi Lithos

20

큰 도전. 여기 내 해결책이 있습니다. 나는 원래 만화에 가능한 한 가깝게하려고 노력했으며, 심지어 xkcd 글꼴을 사용했습니다 .

WPF 응용 프로그램이지만 System.Drawing게으 르기 때문에 그리기 부분을 수행했습니다.

기본 개념 : WPF에서 windows는 Visuals이므로 렌더링 할 수 있습니다. 전체 Window 인스턴스를 비트 맵으로 렌더링하고, 검정 및 총 검정 또는 흰색을 세고 (글꼴 다듬기 및 기타 항목의 회색은 무시) 이미지의 각 3 번째 (각 패널)에 대해이를 세어 계산합니다. 그런 다음 타이머에서 다시 수행합니다. 1-2 초 안에 평형에 도달합니다.

다운로드:

MEGA 항상 바이러스 등을 위해 다운로드 한 파일을 확인하십시오.

당신이 그것을보고 싶다면 위의 글꼴을 시스템에 설치해야합니다. 그렇지 않으면 WPF 기본 글꼴입니다.

XAML :

<Window
 x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="xkcd: 688" Height="300" Width="1000" WindowStyle="ToolWindow">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.3*"/>
            <ColumnDefinition Width="0.3*"/>
            <ColumnDefinition Width="0.3*"/>
        </Grid.ColumnDefinitions>

        <Border BorderBrush="Black" x:Name="bFirstPanel" BorderThickness="3" Padding="10px" Margin="0 0 10px 0">
            <Grid>
                <Label FontSize="18" FontFamily="xkcd" VerticalAlignment="Top">Fraction of this window that is white</Label>
                <Label FontSize="18" FontFamily="xkcd" VerticalAlignment="Bottom">Fraction of this window that is black</Label>
                <Image x:Name="imgFirstPanel"></Image>
            </Grid>
        </Border>
        <Border Grid.Column="1" x:Name="bSecondPanel" BorderBrush="Black" BorderThickness="3" Padding="10px" Margin="10px 0">
            <Grid>
                <TextBlock FontSize="18" FontFamily="xkcd" VerticalAlignment="Top" HorizontalAlignment="Left">Amount of <LineBreak></LineBreak>black ink <LineBreak></LineBreak>by panel:</TextBlock>
                <Image x:Name="imgSecondPanel"></Image>
            </Grid>
        </Border>
        <Border Grid.Column="2" x:Name="bThirdPanel" BorderBrush="Black" BorderThickness="3" Padding="10px" Margin="10px 0 0 0">
            <Grid>
                <TextBlock FontSize="18" FontFamily="xkcd" VerticalAlignment="Top" HorizontalAlignment="Left">Location of <LineBreak></LineBreak>black ink <LineBreak></LineBreak>in this window:</TextBlock>
                <Image x:Name="imgThirdPanel"></Image>
            </Grid>
        </Border>

    </Grid>
</Window>

암호:

using System;
using System.Drawing;
using System.Timers;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Brushes = System.Drawing.Brushes;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        private Timer mainTimer = new Timer();
        public MainWindow()
        {
            InitializeComponent();

            Loaded += (o1,e1) =>
                          {
                              mainTimer = new Timer(1000/10);
                              mainTimer.Elapsed += (o, e) => {
                                  try
                                  {
                                      Dispatcher.Invoke(Refresh);
                                  } catch(Exception ex)
                                  {
                                      // Nope
                                  }
                              };
                              mainTimer.Start();
                          };
        }

        private void Refresh()
        {
            var actualh = this.RenderSize.Height;
            var actualw = this.RenderSize.Width;

            var renderTarget = new RenderTargetBitmap((int) actualw, (int) actualh, 96, 96, PixelFormats.Pbgra32);
            var sourceBrush = new VisualBrush(this);

            var visual = new DrawingVisual();
            var context = visual.RenderOpen();

            // Render the window onto the target bitmap
            using (context)
            {
                context.DrawRectangle(sourceBrush, null, new Rect(0,0, actualw, actualh));
            }
            renderTarget.Render(visual);

            // Create an array with all of the pixel data
            var stride = (int) actualw*4;
            var data = new byte[stride * (int)actualh];
            renderTarget.CopyPixels(data, stride, 0);

            var blackness = 0f;
            var total = 0f;

            var blacknessFirstPanel = 0f;
            var blacknessSecondPanel = 0f;
            var blacknessThirdPanel = 0f;
            var totalFirstPanel = 0f;
            var totalSecondPanel = 0f;
            var totalThirdPanel = 0f;

            // Count all of the things
            for (var i = 0; i < data.Length; i += 4)
            {
                var b = data[i];
                var g = data[i + 1];
                var r = data[i + 2];

                if (r == 0 && r == g && g == b)
                {
                    blackness += 1;
                    total += 1;

                    var x = i%(actualw*4) / 4;

                    if(x < actualw / 3f)
                    {
                        blacknessFirstPanel += 1;
                        totalFirstPanel += 1;
                    } else if (x < actualw * (2f / 3f))
                    {
                        blacknessSecondPanel += 1;
                        totalSecondPanel += 1;
                    }
                    else if (x < actualw)
                    {
                        blacknessThirdPanel += 1;
                        totalThirdPanel += 1;
                    }
                } else if (r == 255 && r == g && g == b)
                {
                    total += 1;

                    var x = i % (actualw * 4) / 4;

                    if (x < actualw / 3f)
                    {
                        totalFirstPanel += 1;
                    }
                    else if (x < actualw * (2f / 3f))
                    {
                        totalSecondPanel += 1;
                    }
                    else if (x < actualw)
                    {
                        totalThirdPanel += 1;
                    }
                }
            }

            var black = blackness/total;

            Redraw(black, blacknessFirstPanel, blacknessSecondPanel, blacknessThirdPanel, blackness, renderTarget);
        }

        private void Redraw(double black, double firstpanel, double secondpanel, double thirdpanel, double totalpanels, ImageSource window)
        {
            DrawPieChart(black);
            DrawBarChart(firstpanel, secondpanel, thirdpanel, totalpanels);
            DrawImage(window);
        }

        void DrawPieChart(double black)
        {
            var w = (float)bFirstPanel.ActualWidth;
            var h = (float)bFirstPanel.ActualHeight;
            var padding = 0.1f;

            var b = new Bitmap((int)w, (int)h);
            var g = Graphics.FromImage(b);

            var px = padding*w;
            var py = padding*h;

            var pw = w - (2*px);
            var ph = h - (2*py);

            g.DrawEllipse(Pens.Black, px,py,pw,ph);

            g.FillPie(Brushes.Black, px, py, pw, ph, 120, (float)black * 360);

            g.DrawLine(Pens.Black, 30f, h * 0.1f, w / 2 + w * 0.1f, h / 2 - h * 0.1f);
            g.DrawLine(Pens.Black, 30f, h - h * 0.1f, w / 2 - w * 0.2f, h / 2 + h * 0.2f);

            imgFirstPanel.Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(b.Width, b.Height));
        }

        void DrawBarChart(double b1, double b2, double b3, double btotal)
        {
            var w = (float)bFirstPanel.ActualWidth;
            var h = (float)bFirstPanel.ActualHeight;
            var padding = 0.1f;

            var b = new Bitmap((int)w, (int)h);
            var g = Graphics.FromImage(b);

            var px = padding * w;
            var py = padding * h;

            var pw = w - (2 * px);
            var ph = h - (2 * py);

            g.DrawLine(Pens.Black, px, py, px, ph+py);
            g.DrawLine(Pens.Black, px, py + ph, px+pw, py+ph);

            var fdrawbar = new Action<int, double>((number, value) =>
                {
                    var height = ph*(float) value/(float) btotal;
                    var width = pw/3f - 4f;

                    var x = px + (pw/3f)*(number-1);
                    var y = py + (ph - height);

                    g.FillRectangle(Brushes.Black, x, y, width, height);
                });

            fdrawbar(1, b1);
            fdrawbar(2, b2);
            fdrawbar(3, b3);

            imgSecondPanel.Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(b.Width, b.Height));
        }

        void DrawImage(ImageSource window)
        {
            imgThirdPanel.Source = window;
        }
    }
}

코드가 정리되지 않았지만 읽을 수 있어야합니다. 죄송합니다.


2
늦은 입장이지만 최고 중 하나입니다.
primo

14

C (SDL 및 SDL_ttf 사용) : 그레이 스케일 솔루션

다음은 파이 차트 양식을 활용하여 100 개 라인 미만의 클럭으로 전체 그레이 스케일 픽셀 색상 스펙트럼을 캡처하는 솔루션입니다.

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "SDL.h"
#include "SDL_ttf.h"

int main(void)
{
    SDL_Surface *screen, *buffer, *caption;
    SDL_Color pal[256];
    SDL_Rect rect;
    SDL_Event event;
    TTF_Font *font;
    int levels[256], plev[256];
    Uint8 *p;
    float g;
    int cr, redraw, hoffset, h, n, v, w, x, y;

    SDL_Init(SDL_INIT_VIDEO);
    TTF_Init();
    screen = SDL_SetVideoMode(640, 480, 0, SDL_ANYFORMAT | SDL_RESIZABLE);
    font = TTF_OpenFont(FONTPATH, 24);
    buffer = 0;
    for (;;) {
        if (!buffer) {
            buffer = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h,
                                          8, 0, 0, 0, 0);
            for (n = 0 ; n < 256 ; ++n)
                pal[n].r = pal[n].g = pal[n].b = n;
            SDL_SetColors(buffer, pal, 0, 256);
        }
        memcpy(plev, levels, sizeof levels);
        memset(levels, 0, sizeof levels);
        SDL_LockSurface(buffer);
        p = buffer->pixels;
        for (h = 0 ; h < buffer->h ; ++h) {
            for (w = 0 ; w < buffer->w ; ++w)
                ++levels[p[w]];
            p += buffer->pitch;
        }
        for (n = 1 ; n < 256 ; ++n)
            levels[n] += levels[n - 1];
        redraw = memcmp(levels, plev, sizeof levels);
        if (redraw) {
            SDL_UnlockSurface(buffer);
            SDL_FillRect(buffer, NULL, 255);
            caption = TTF_RenderText_Shaded(font,
                        "Distribution of pixel color in this image",
                        pal[0], pal[255]);
            rect.x = (buffer->w - caption->w) / 2;
            rect.y = 4;
            hoffset = caption->h + 4;
            SDL_BlitSurface(caption, NULL, buffer, &rect);
            SDL_FreeSurface(caption);
            SDL_LockSurface(buffer);
            cr = buffer->h - hoffset;
            cr = (cr < buffer->w ? cr : buffer->w) / 2 - 4;
            p = buffer->pixels;
            for (h = 0 ; h < buffer->h ; ++h) {
                y = h - (screen->h + hoffset) / 2;
                for (w = 0 ; w < buffer->w ; ++w) {
                    x = w - buffer->w / 2;
                    g = sqrtf(x * x + y * y);
                    if (g < cr - 1) {
                        g = atanf((float)y / (x + g));
                        v = levels[255] * (g / M_PI + 0.5);
                        for (n = 0 ; n < 255 && levels[n] < v ; ++n) ;
                        p[w] = n;
                    } else if (g < cr + 1) {
                        p[w] = (int)(128.0 * fabs(g - cr));
                    }
                }
                p += buffer->pitch;
            }
        }
        SDL_UnlockSurface(buffer);
        SDL_BlitSurface(buffer, NULL, screen, NULL);
        SDL_UpdateRect(screen, 0, 0, 0, 0);
        if (redraw ? SDL_PollEvent(&event) : SDL_WaitEvent(&event)) {
            if (event.type == SDL_QUIT)
                break;
            if (event.type == SDL_VIDEORESIZE) {
                SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
                                 SDL_ANYFORMAT | SDL_RESIZABLE);
                SDL_FreeSurface(buffer);
                buffer = 0;
            }
        }
    }
    SDL_Quit();
    TTF_Quit();
    return 0;
}

이전 솔루션과 마찬가지로 글꼴 파일의 경로는 소스에서 하드 코딩하거나 빌드 명령에 추가해야합니다.

gcc -Wall -o xkcdgolf `sdl-config --cflags`
    -DFONTPATH=`fc-match --format='"%{file}"' :bold`
    xkcdgolf.c -lSDL_ttf `sdl-config --libs` -lm

프로그램의 출력은 다음과 같습니다 :

전체 회색조 픽셀 색상 분포를 보여주는 원형 차트

모든 수학은 안정적인 솔루션에서 프로그램이 0으로 보이는 위치로 다시 그리기 속도를 늦추기 때문에 보는 것이 재미 있습니다. 첫 번째 추정치는 표면이 완전히 검은 색으로 시작되므로 심각하게 벗어난 후 약 12 ​​회 정도 반복 한 후에 최종 크기로 축소됩니다.

이 코드는 현재 이미지에서 각 픽셀 색상의 인구 수를 계산하여 작동합니다. 이 모집단 개수가 마지막 개수와 일치하지 않으면 이미지를 다시 그립니다. 이 코드는 모든 픽셀을 반복하지만 x, y 좌표를 극좌표로 변환하여 먼저 반경을 계산합니다 (이미지의 중심을 원점으로 사용). 반경이 원형 차트 영역 내에 있으면 세타를 계산합니다. 세타는 픽셀 수를 결정하는 모집단 수에 따라 쉽게 조정됩니다. 반면에 반경이 원형 차트의 경계에 있으면 앤티 앨리어싱 된 값이 계산되어 차트 외부 주위에 원이 그려집니다. 극좌표는 모든 것을 쉽게 만듭니다!


당신은 대부분 사용하고있는 float수학 라이브러리 함수의 버전을,하지만하지 말아야 fabsfabsf?
luser droog

아마도 기술적으로 fabs()는 더 이식성이 뛰어납니다.
breadbox

사실, 라이브러리에있는 경우에도 헤더에 정의되지 않은 문제가 있습니다. 또한 초월적인 것보다 얻는 성능이 떨어집니다. :)
luser droog

10

C (SDL 및 SDL_ttf 포함)

약 60 줄의 C 코드로 된 매우 간단한 구현은 다음과 같습니다.

#include <stdio.h>
#include "SDL.h"
#include "SDL_ttf.h"

int main(void)
{
    char buf[64];
    SDL_Surface *screen, *text;
    SDL_Rect rect;
    SDL_Color black;
    SDL_Event event;
    TTF_Font *font;
    Uint32 blackval, *p;
    int size, b, prevb, h, i;

    SDL_Init(SDL_INIT_VIDEO);
    TTF_Init();
    screen = SDL_SetVideoMode(640, 480, 32, SDL_ANYFORMAT | SDL_RESIZABLE);
    font = TTF_OpenFont(FONTPATH, 32);
    black.r = black.g = black.b = 0;
    blackval = SDL_MapRGB(screen->format, 0, 0, 0);

    b = -1;
    for (;;) {
        prevb = b;
        b = 0;
        SDL_LockSurface(screen);
        p = screen->pixels;
        for (h = screen->h ; h ; --h) {
            for (i = 0 ; i < screen->w ; ++i)
                b += p[i] == blackval;
            p = (Uint32*)((Uint8*)p + screen->pitch);
        }
        SDL_UnlockSurface(screen);
        size = screen->w * screen->h;
        SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
        sprintf(buf, "This image is %.2f%% black pixels", (100.0 * b) / size);
        text = TTF_RenderText_Solid(font, buf, black);
        rect.x = (screen->w - text->w) / 2;
        rect.y = screen->h / 2 - text->h;
        SDL_BlitSurface(text, NULL, screen, &rect);
        SDL_FreeSurface(text);
        sprintf(buf, "and %.2f%% white pixels.", (100.0 * (size - b)) / size);
        text = TTF_RenderText_Solid(font, buf, black);
        rect.x = (screen->w - text->w) / 2;
        rect.y = screen->h / 2;
        SDL_BlitSurface(text, NULL, screen, &rect);
        SDL_FreeSurface(text);
        SDL_UpdateRect(screen, 0, 0, 0, 0);
        if (b == prevb ? SDL_WaitEvent(&event) : SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT)
                break;
            if (event.type == SDL_VIDEORESIZE)
                SDL_SetVideoMode(event.resize.w, event.resize.h, 32,
                                 SDL_ANYFORMAT | SDL_RESIZABLE);
        }
    }

    TTF_Quit();
    SDL_Quit();
    return 0;
}

이를 컴파일하려면 FONTPATH사용할 글꼴의 .ttf 파일을 가리 키도록 정의해야 합니다.

gcc -Wall -o xkcdgolf `sdl-config --cflags`
    -DFONTPATH='"/usr/share/fonts/truetype/freefont/FreeSansBold.ttf"'
    xkcdgolf.c -lSDL_ttf `sdl-config --libs`

대부분의 최신 Linux 시스템에서는 fc-match유틸리티를 사용하여 글꼴 위치를 찾을 수 있으므로 컴파일 명령은 다음과 같습니다.

gcc -Wall -o xkcdgolf `sdl-config --cflags`
    -DFONTPATH=`fc-match --format='"%{file}"' :bold`
    xkcdgolf.c -lSDL_ttf `sdl-config --libs`

(물론 요청한 글꼴을 개인적으로 좋아하는 글꼴로 바꿀 수 있습니다.)

이 코드는 앤티 앨리어싱을 요구하지 않으므로 창에는 흑백 픽셀 만 포함됩니다.

마지막으로, 창 크기 조정을 허용하는 @daniero의 우아한 솔루션에서 영감을 얻었습니다. 때로는 프로그램이 카운트 사이에서 진동하고 절대 도달 할 수없는 어 트랙터 주위의 궤도에 갇혀 있음을 알 수 있습니다. 그런 경우에는 멈출 때까지 창의 크기를 약간 조정하십시오.

그리고 요청마다 시스템에서 실행할 때의 모습은 다음과 같습니다.

이 이미지는 검정 픽셀 3.36 % 및 흰색 픽셀 96.64 %입니다.

마지막으로, 나는 여기에 아무도 그것을 보지 못했다면 MAA 가 랜달 먼로와의 인터뷰를 발표 하여 만화 # 688의 제작에 대해 자세히 설명했다고 생각합니다.


1
아주 좋은 해결책. @daniero의 게시물을 따라 실행중인 프로그램의 스크린 샷을 넣을 수 있습니까? :)
Alex Brooks

+1, 아주 좋아요! 스크린 샷을 추가해 주셔서 감사합니다 :) 그리고 인터뷰 링크가 흥미 롭습니다. 감사합니다!
WendiKidd

9

여기에 이미지 설명을 입력하십시오

이미지는 100x100이고 숫자는 정확하며 정확히 의미합니다. 백분율을 소수점 이하 두 자리로 표현할 수 있도록 10000 픽셀 이미지를 선택했습니다. 이 방법은 약간의 수학, 약간의 추측 및 파이썬의 숫자 크 런칭이었습니다.

내가 백분율을 4 자리수로 표현할 수 있다는 것을 미리 알았을 때, 나는 텍스트가 쓰여진 8 픽셀 높이 Arial에서 0에서 9까지의 각 숫자에 얼마나 많은 검은 픽셀이 있는지 계산했습니다. weight주어진 숫자를 쓰기 위해 필요한 픽셀 수를 알려주는 빠른 기능 , 0으로 채워져 4 자리 숫자를 갖습니다.

def weight(x):
    total = 4 * px[0]
    while x > 0:
       total = total - px[0] + px[x % 10]
       x = x / 10
    return total

px숫자를 필요한 픽셀 수에 매핑하는 배열입니다. B가 검은 색 픽셀의 수이고 W가 ​​흰색의 픽셀 수이면 B + W = 10000를가집니다.

B = 423 + weight(B) + weight(W)
W = 9577 - weight(B) - weight(W)

상수는 어디에서 왔습니까? 423은 숫자가없는 텍스트의 검은 색 픽셀 수인 "초기"검은 색 픽셀 수입니다. 9577은 초기 흰색 픽셀의 수입니다. 위의 시스템에 솔루션이 있도록 상수를 얻기 전에 초기 검은 픽셀의 양을 여러 번 조정해야했습니다. 이것은 내 손가락을 추측하고 교차시킴으로써 이루어졌습니다.

위의 시스템은 엄청나게 비선형이기 때문에 분명히 상징적으로 해결하는 것을 잊을 수는 있지만 B의 모든 값을 반복하고 W = 10000-B를 설정하고 방정식을 명시 적으로 확인하면됩니다.

>>> for b in range(10000 + 1):
...     if b == weight(b) + weight(10000 - b)+423: print b;
...
562
564

250 x 400 이미지를 사용하여 소수점 이하 3 자리까지 가져 가면서 더 많은 텍스트를 표시 할 수 있습니다.
Joe Z.

아주 좋은 해결책, 일부 무차별 수학은 항상 이런 종류의 문제를 해결할 수 있습니다!
CCP

6

Q 기본

향수 때문에.

그리고 이미지 라이브러리가 현대 언어라는 것을 실제로 알지 못하기 때문입니다.

SCREEN 9

CONST screenWidth = 640
CONST screenHeight = 350
CONST totalPixels# = screenWidth * screenHeight

accuracy = 6

newWhite# = 0
newGreen# = 0
newBlack# = totalPixels#

DO
    CLS
    white# = newWhite#
    green# = newGreen#
    black# = newBlack#

    ' Change the precision of the percentages every once in a while
    ' This helps in finding values that converge
    IF RND < .1 THEN accuracy = INT(RND * 4) + 2
    format$ = "###." + LEFT$("######", accuracy) + "%"

    ' Display text
    LOCATE 1
    PRINT "Percentage of the screen which is white:";
    PRINT USING format$; pct(white#)
    LOCATE 4
    PRINT white#; "/"; totalPixels#; "pixels"
    LOCATE 7
    PRINT "Percentage of the screen which is black:";
    PRINT USING format$; pct(black#)
    LOCATE 10
    PRINT black#; "/"; totalPixels#; "pixels"
    LOCATE 13
    PRINT "Percentage of the screen which is green:";
    PRINT USING format$; pct(green#)
    LOCATE 16
    PRINT green#; "/"; totalPixels#; "pixels"

    ' Display bar graphs
    LINE (0, 16)-(pct(white#) / 100 * screenWidth, 36), 2, BF
    LINE (0, 100)-(pct(black#) / 100 * screenWidth, 120), 2, BF
    LINE (0, 184)-(pct(green#) / 100 * screenWidth, 204), 2, BF

    newBlack# = pixels#(0)
    newGreen# = pixels#(2)
    newWhite# = pixels#(15)
LOOP UNTIL black# = newBlack# AND white# = newWhite# AND green# = newGreen#

' Wait for user keypress before ending program: otherwise the "Press any
' key to continue" message would instantly make the results incorrect!
x$ = INPUT$(1)


FUNCTION pixels# (colr)
' Counts how many pixels of the given color are on the screen

pixels# = 0

FOR i = 0 TO screenWidth - 1
    FOR j = 0 TO screenHeight - 1
        IF POINT(i, j) = colr THEN pixels# = pixels# + 1
    NEXT j
NEXT i

END FUNCTION

FUNCTION pct (numPixels#)
' Returns percentage, given a number of pixels

pct = numPixels# / totalPixels# * 100

END FUNCTION

매우 간단한 출력 카운트 반복 방법입니다. 중요한 "흥미로운"것은 프로그램이 무작위로 백분율에 대해 다른 정밀도를 시도한다는 것입니다.

그리고 출력 ( QB64에서 테스트 ) :

Q 기본 메타 그래프


3

AWK

... netpbm 및 기타 도우미와 함께

'x'파일 :

BEGIN {
        FS=""
        n++
        while(n!=m) {
                c="printf '%s\n' '"m"% black pixels'"
                c=c" '"100-m"% white pixels'"
                c=c" | pbmtext -space 1 -lspace 1 | pnmtoplainpnm | tee x.pbm"
                n=m
                delete P
                nr=0
                while(c|getline==1) if(++nr>2) for(i=1;i<=NF;i++) P[$i]++
                close(c)
                m=100*P[1]/(P[0]+P[1])
                print m"%"
        }
}

질주:

$ awk -f x
4.44242%
5.2424%
5.04953%
5.42649%
5.27746%
5.1635%
5.15473%
5.20733%
5.20733%

사진은 'x.pbm'으로 작성되었으며 업로드를 위해 png로 변환했습니다.

x.png

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.