xkcdチャレンジ:「[x]色の画面の割合」


57

だから私たちはおそらくこのxkcdコミックを見たことがあると思います:

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

これは一般的すぎるか、難しすぎるかもしれませんが、わかりません。しかし、課題は、少なくとも2色のウィンドウを作成し、画面の何パーセントが各色であるかを英語で表示する任意の言語でプログラムを作成することです。

例 最も簡単な解決策は、「黒のこの画像の割合:[x]%。この画像の白の割合:[y]%」と書かれた黒い文字の白い背景です。

好きなだけ夢中にしたり、シンプルにしたりできます。プレーンテキストは有効な解決策ですが、xkcdコミックのように面白い画像を作成する場合はさらに優れています。勝者は、最も多くの票を獲得する最も楽しく創造的なソリューションになります。だから、xkcdにふさわしいものを作りましょう!:)

それで、あなたはどう思いますか?楽しいチャレンジのように聞こえますか?:)

回答に実行中のプログラムのスクリーンショットを含めてください:)


6
プログラムより面白い:-)だろう「このプログラムは、64 Aの、4件のBさん、...と、ソースコード内の34個の二重引用符を持っている」
ジョン・ドヴォルザーク

2
OK ...客観的な勝利基準は何ですか?特定の出力が有効かどうかをどのように判断しますか?それが真実であり、それ自体の特性を数値的に記述すれば十分ですか?
ジョンドボラック

@JanDvorakああ、それは良いものです!アルファベットプログラムは、実際にこのことを最初に考えさせたものですが、ソースコード要素を追加することは考えていませんでした!それを質問として投稿する必要があります:)はい、それは真実であり、それ自体を説明するだけで十分です。うーん、あなたは正しいですが、最終結果が正しいことをどのように証明するかについては考えませんでした。結果画像の各色のすべてのピクセルを数える方法が必要だと思います。今すぐ調べに行きます。(申し訳ありませんが私の最初の質問に問題がありました...私は試しましたが、私はこれに新しいです!ありがとう:))
WendiKidd

真実性と自己参照が十分な基準である場合、ここに私のゴルフスクリプト競技者がいます:("/.*/"読む:[ソースコード]には改行が含まれていません)
ジョンドヴォルザーク

@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
抜け穴!
ティムテック14年

これ大好き!!!少なくとも今のところ、あなたはまったく賢いポイントにチェックマークを付けます。大好きです!
WendiKidd 14年

13
最良の部分は、どの文がどの色について話しているのかまだわかりません。
ブリリアンド14年

3
これview sourceはshare-elm.comによってそこに置かれ、コンパイルされたJS / HTMLの一部ではありません。
hoosierEE

1
@ML「this」という単語の範囲に依存します。JavaScriptプログラマーは理解しています...
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
ウェンディキッド

1
印象的な作品のオブジェクト指向
izabera

気の利いた...しかし、私はそれが「解決策」になるために安定しなければならないと思います。完全に考え抜いたことはありませんが、限られた数字のグリフセットから描画する場合、必ずしも任意の精度の解決策はないため、より高い精度で解決できない場合は精度を下げる必要がありますあなたがしようとしている。黒/白ピクセルを事前に計算する等幅フォントを使用することも必要になると思います。
レブム博士14年

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!(私は興味がありますが、なぜ時間が経つにつれて遅くなり、正しい割合に近づくのですか?私は何が起こっているのか興味があります、私はこの言語を見たことがありません。このサイトの周辺にはたくさんの新しいものが
突っ込んでい

ヘッドデスク私が誤って+1をクリックするのを忘れたことを除いて。 +1 ...(笑)。ごめんなさい!
WendiKidd

1
ユーザーがインタラクティブ機能を追加するために、ユーザーがマウスで描画できるようにする別の関数を追加できます。
AJMansfield

7
ホーリーボックスシャドウ、バットマン
ボジャングルズ

ゴルフをしたい場合は、background(-1)代わりに使用できますbackground(255)
Kritixi Lithos

20

大きな挑戦。これが私の解決策です。私はオリジナルのコミックにできるだけ近づけようとしましたが、xkcdフォントも使用しました。

これはWPFアプリケーションですが、System.Drawing私は怠け者なので描画部分を使用していました。

基本概念:WPFでは、ウィンドウは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
遅刻ですが、最高の1つです。
プリモ

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

プログラムの出力は次のようになります。

完全なグレースケールピクセルカラー分布を示す円グラフ

これは、すべての数学が再描画の速度を低下させ、安定したソリューションでプログラムがゼロになるのを見ることができるので、見るのが楽しいです。最初の推定値は(表面が真っ黒になっているため)乱暴にオフになっており、約10回程度の反復の後、最終サイズまで縮小します。

コードは、現在の画像の各ピクセル色の人口カウントを取得することで機能します。この人口カウントが最後の人口カウントと一致しない場合、画像を再描画します。コードはすべてのピクセルを反復処理しますが、x、y座標を極座標に変換し、最初に半径を計算します(画像の中心を原点として使用)。半径が円グラフ領域内にある場合、シータが計算されます。シータは、ピクセル数を決定する人口カウントに簡単にスケーリングできます。一方、半径が円グラフの境界上にある場合は、アンチエイリアス値が計算されてグラフの外側に円が描かれます。極座標はすべてを簡単にします!


ほとんどの場合、float数学ライブラリ関数のバージョンを使用していますが、使用すべきではありませfabsfabsfか?
luserのドローグ

おそらく技術的には、おそらくfabs()よりポータブルです。
パンボックス

確かに、ライブラリに存在する場合でもヘッダーで定義されていないという問題がありました。また、超越者よりも得られるパフォーマンスは低くなります。:)
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 がRandall Munroeとのインタビューを公開し漫画#688の作成についてある程度詳しく話し合うことを指摘すべきだと思います。


1
とてもいい解決策。@danieroの投稿に続いて、実行中のプログラムのスクリーンショットをいくつか入れていただけますか?:)
アレックスブルックス

+1、とてもいい!スクリーンショットを追加してくれてありがとう:)そしてインタビューのリンクは面白いです、ありがとう!
WendiKidd

9

ここに画像の説明を入力してください

画像は100x100で、数値は正確です。つまり、正確に意味します-パーセンテージを小数点以下2桁で表現できるように、10000ピクセルの画像を選択しました。このメソッドは、Pythonでのちょっとした計算、ちょっとした推測、およびいくつかの計算処理でした。

パーセンテージが4桁で表現できることを事前に知っていたので、高さ8ピクセルのArialで、0〜9の各桁に黒ピクセルがいくつあるかをカウントしました。weight指定された数値を書き込むために必要なピクセル数を示すクイック関数。左にゼロを埋めて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桁まで取得し、その間により多くのテキストを表示することができます。
ジョーZ. 14年

非常に優れたソリューションであり、ブルートフォースの数学は常にこの種の問題を解決できます!
CCP 14年

6

QBasic

懐かしいから。

また、画像ライブラリが最新の言語であることはよくわからないためです。

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でテスト済み):

QBasicメタグラフ


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.