暗闇で文字を並べ替える


38

プログラムは、次のように入力として文字の行を受け取る必要があります。

@+.0

そして、次のように、文字を暗さでソートして出力します。

.+0@

要件:

  • 暗闇の検出には等幅フォントを使用する必要があります。

  • 各文字が占めるピクセル数を調べる必要があります。実際に文字を描画してピクセルをカウントする必要があります。つまり、ピクセル量をハードコーディングすることはできません。

    • より具体的なルールとして、フォントを切り替えてもプログラムは機能するはずです。さらに、プログラムは、コード内の変数、値、または文字列を変更するだけでフォントを切り替えることができる必要があります。
  • アンチエイリアスを使用する場合、ピクセルを完全に黒いピクセルの割合としてカウントする必要があります。たとえば、rgb(32, 32, 32)ピクセルはフルピクセルの1/8としてカウントされます。キャラクターがアンチエイリアス処理されていない場合、このルールを無視してください。

  • ピクセルをカウントした後、ピクセルの量で文字をソートし、順番に出力する必要があります。

  • これはなので、バイト単位の最短コードが優先されます。


7
奇妙なことに、これはRPG.seにも適しています!
corsiKa 14年

1
暗闇の計算で表示ガンマの補正はありませんか?
イルマリカロネン14年

6
白いフォントを使用できますか?もしそうなら、私はこれをラップしたと思う。
ポール14年

回答:


22

Mathematica、112 110 108バイト

これはまださらにゴルフすることができます。文字列が変数sにあると仮定します。

また、正しい構文を使用して、あるリストを別のリストでソートします。
ラッキーテストケース->「ああ、そうだ」-> Facepalm
鋭い目をありがとう、David Carraher。

更新: OCR AをMenloに置き換えました。OSXでは、OCR Aフォントファミリ名は実際にはOCR A Stdであることがわかったためです。だから私は本当の取引の代わりにデフォルトのフォントをソートしていました。Menloも同じバイト数で等幅になっているため、正味のゲインやロスはありません。

ノートブックのホストされたCDFエクスポートを作成したので、必要に応じて実行中のコードを確認できます。WebでホストされるCDFにインタラクティブ機能を追加する方法をまだ考えているので、今のところは静的です。

c=Characters@s;Last/@Sort[Transpose@{Total[1-#&/@ImageData@Rasterize@Style[#,FontFamily->"Menlo"],3]&/@c,c}]

s = FromCharacterCode /@ Range[33, 135];「Courier」での出力

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

同じものを出力しますが、FontFamily "Monospace"を使用します。

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

最終結果は、ソートされているフォントではなく、MMの内部フォントで表示されることに注意してください。したがって、選択したフォントの違いがソートに反映されます。ただし、CDFリンクには、完了者の両方が表示されます。

未ゴルフコード:

s = FromCharacterCode /@ Range[33, 135];
c = Characters@s;
Last /@ Sort[
    Transpose@{Total[1 - # & /@ 
        ImageData@Rasterize@Style[#, FontFamily -> "Menlo"], 3] & /@ c, c}]

1
この入力を調べます"" <> (FromCharacterCode /@ Range[33, 135])
DavidC

デフォルトのファミリーであろうとなかろうと、スペックは「プログラムは単に変数を変更するだけでフォントを切り替えることができるはずです」。アンチエイリアシングの値のために、いくつかの種類が間違って見える可能性がありますが、全範囲をもう一度見て、何か間違っているかどうかを確認します。
ジョナサンヴァンマトレ14年

1
なんて素晴らしい言語でしょう!先日、Wolframによる新しいプログラミング言語の取り組みについて知り、それを楽しみにしていました。
the0ther

1
Characters []をCharacters @に、Reverse []をReverse @に変更すると、2バイトを節約できます。
マイケルスターン14年

2
私は同様の答えを投稿する必要はありませんが、私は自分自身を試してみましたが、それが短い思い付いたStringJoin@SortBy[Characters@"@+.0",ImageData@Binarize@Rasterize@Style[#,FontFamily->"Monospace"]~Total~2&]
パッ

25

Bash + ImageMagick:164 147 148文字

while read -n1 c
do
o=`convert -size 20x15 xc: +antialias -font cour.ttf -draw "text 0,10 '$c'" xpm:-`
o=${o//[^ ]}
a[${#o}]+=$c
done
echo "${a[@]}"

サンプル実行:

bash-4.1$ echo -n '@+.0' | bash graysort.sh
. + 0 @

グレーグループ間にセパレータが挿入されます。同じグレーレベルの文字は分離されていません:

bash-4.1$ echo -n 'abcdefghijklmnopqrstuvwxyz' | bash graysort.sh
i cl jortz esv ax u df bgnpq y hk w m

+1の代わりにbash配列インデックスを使用した並べ替えsort
Digital Trauma 14年

9

QBasic、259バイト

SCREEN 1
DIM a(255)
FOR i = 32 TO 255
    CLS
    PRINT CHR$(i);
    FOR p = 0 TO 64
        a(i) = a(i) + POINT(p MOD 8, p \ 8)
    NEXT p
NEXT i
FOR p = 0 TO 96
    FOR i = 32 TO 255
        IF a(i) = p THEN PRINT CHR$(i);
    NEXT i
NEXT p

私は楽しみのためにこれを行ったので、ある意味では技術的にルールに準拠していません。文字のリストは受け取りませんが、代わりに32-255のすべての文字を出力し、代わりにそれを使用します。このルールに準拠したバージョンを本当に見たい場合は、教えてください。

また、別の技術的問題もあります。「さらに、プログラムは、コード内の変数、値、または文字列を変更するだけでフォントを切り替えることができるはずです。」QBasic内からこれを行う簡単な方法はありません。ただし、プログラムはもちろん、任意のコードページで正常に機能します。

最後に、いくつかの文字(QBasic IDEが有用に挿入するほとんどの空白)を絞ることができますが、この答えはとにかく勝つチャンスがないので、おそらく価値がありません。

QBasic暗闇による文字のソート


楽しみのためにそれを行うためのプラス!
ジョナサンヴァンマトレ14年

8

Javascriptを+キャンバスやブラウザのDOM(280 237 235バイト)

コメントのForsと歯ブラシからの提案で更新されたバージョン:

function m(x){a=document.createElement('canvas').getContext('2d');a.font='9px Monaco';a.fillText(x,y=i=0,20);for(;i<3600;)y+=a.getImageData(0,0,30,30).data[i++];return y}alert(s.split('').sort(function(a,b){return m(a)-m(b)}).join(''))

より読みやすいバージョン:

// Scoring function - Calculates darkness for single character
function m(x) {
    a = document.createElement('canvas').getContext('2d');
    a.font = '9px Monaco';
    a.fillText(x, y = i = 0, 20);
    for (; i < 3600;) y += a.getImageData(0, 0, 30, 30).data[i++];
    return y
}
// Assume input is in variable s and alert as output. Comparison function now expression.
alert(s.split('').sort(function (a, b) {
    return m(a) - m(b)
}).join(''))

もっとゴルフできるかもしれません。

私はこのサイトを初めて使用するので、Javascriptの回答の入力が通常どのように読み取られるかわかりません。入力はという名前の変数に含まれていると仮定しますs。これで問題がなければ、答えと文字数を更新します。

更新バージョンのJSFiddle。

JSFiddleの最初のバージョン


本当に気に入っていますが、ここには多くの改善点があります。変数csは不要です(a=document.createElement('canvas').getContext('2d')およびy+=a.getImageData(0,0,30,30).data[i])、要素を追加する必要はありません、のゼロ初期化yii=y=0)のゼロ初期化と組み合わせることができ、ポストインクリメントiyfor(...;y+=...[i++]);)の追加と組み合わせることができ、書体モナコは等幅で、クーリエよりも短い名前を持っています。
Fors

ありがとう!私はまだベテランのゴルファーではないので、あなたのコメントは大いに役立ちます。それらをコードに組み込みました。
ワックスウィング14年

ここでのJavascriptの回答は、通常、入力を読み取りますprompt(); しかし、これも問題ありません。
カルティック14年

あなたは削除することができますy=i=0;し、変更a.fillText(x,0,20)しますa.fillText(x,y=i=0,20)
歯ブラシ14年

おかげで、それも追加されました!二人のキャラクターは二人のキャラクターです!
ワックスウィング14年

3

PHP、298文字

いくつかの改行を追加したので、すべての恐ろしい点を確認できます。

<?php
$s=@$_GET[s];$a=array();$v=imagecreate(16,16);$f='imagecolorallocate';
$f($v,0,0,0);for($i=0;$i<strlen($s);$i++){$c=$f($v,$i,0,1);
imagechar($v,5,2,$n=0,$s[$i],$c);for($y=16;$y--;)
for($x=16;$x--;)$n+=($c==imagecolorat($v,$x,$y));
$a[]=ord($s[$i])+($n<<8);}sort($a);foreach($a as $v)echo chr($v);

このコードは、PHPに組み込まれているGDフォントを使用します。の2番目の引数はimagechar()フォントを選択します(1〜5の数字が有効です)。

例:

Input:  !@#$%^&*-=WEIX,./'
Output: '-.,^=!/*IE%X#$&@W

上記のコードの上に以下を挿入すると、Webブラウザーで文字のリストを提供できるようになります。

<?php
define("FONT_SIZE",5);
if(@$_SERVER['PATH_INFO']=='/a.png') {
  $s = $_GET['s'];
  $im = imagecreate(strlen($s)*(FONT_SIZE+4)+4,FONT_SIZE+12);
  imagecolorallocate($im,255,255,128);
  $c = imagecolorallocate($im,0,0,0);
  imagestring($im,FONT_SIZE,2,0,$s,$c);
  header("Content-Type: image/png");
  imagepng($im);
  imagedestroy($im);
  exit();
}
$me = $_SERVER['PHP_SELF'];
$t1 = $img = "";
if ($t1=htmlspecialchars(@$_GET['s'])) {
  $t2=urlencode($_GET['s']);
  $img="<p><img src=\"$me/a.png?s=$t2\" /></p>";
}
echo <<<END_HTML
<html>
<body>
$img
<form action="$me" method="get">
<input type="text" name="s" size="40" value="$t1" />
<input type="submit" value="Go" />
</form>
END_HTML;
if(!isset($_GET['s'])) exit();
?>

1
使用するimagecreatetruecolor場合は、-11の場合、最初の割り当てを削除して、2番目の割り当てに直接関数名を使用できます。[]代わりにarray()。とforeach($a as$v)同様に
Einacio 14年

3

GTB

これには、電卓用に私が書いたコードの中で2番目に難しいコードがあります。ハードコーディングされたピクセル値はありません。実際にグラフにテキストを描画し、ループして各ピクセルをカウントします。

0→I`_%I<l?_T;1,1,s;_,I,1
C;pT;{0,1,2,3,4,5},{0,1,2}→L1(I
0→I%I<l?_T;1,C;L1(I)>L1,I

入力

,O.i

出力

.,iO

これがうまくいけば、これが最良の答えです。GTBとは何ですか?
スレーター14年

@slaterリンクをクリックして調べてみませんか?
ティムテック14年

投稿のタイトルが実際にリンクであることを指摘していただきありがとうございます。
スレーター14年

2
コンパイラを解読するために必要なソフトウェアを入手するためのドメインは死んでいます。ここでも死んだ。テストするために手作業でコードを翻訳しましたが、10個の括弧を開いて1個だけ閉じたようですので、それを解決する方法がわかりません。私の頭の中のコンパイラは言う:「Error :: unmatched identifier」:)
ジョナサンヴァンマトレ14年

1
@JonathanVanMatre心配しないでください。TI-84は自動的にそれらを閉じます。
ティムテック14年

3

Javaの- 468 450 444

public static void main(String[]a){class c implements Comparable<c>{char d;c(char e){d=e;}public int compareTo(c o){return e(d)>e(o.d)?1:-1;}int e(char f){int a=0,x,y;BufferedImage img=new BufferedImage(99,99,1);img.getGraphics().drawString(""+f,9,80);for(y=0;y<99;y++)for(x=0;x<99;x++)a+=img.getRGB(x,y);return a;}}c[]s=new c[a[0].length()];int i=0;for(char d:a[0].toCharArray())s[i++]=new c(d);Arrays.sort(s);for(c d:s)System.out.print(d.d);}

@+.0abcdefghijklmnopqrstuvwxyz -> .irl+jcvtfxyzsuonkheaqpdb0wgm@

ゴルフをしていない:

    public static void main(String[] a) {
    a = new String[]{"@+.0abcdefghijklmnopqrstuvwxyz"};
    class c implements Comparable<c> {
        char    d;

        c(char e) {
            d = e;
        }

        @Override
        public int compareTo(c o) {
            return e(d) > e(o.d)? 1 : -1;
        }

        int e(char f) {
            int a = 0, x, y;
            BufferedImage img = new BufferedImage(99, 99, 1);
            img.getGraphics().drawString("" + f, 9, 80);
            for (y = 0; y < 99; y++)
                for (x = 0; x < 99; x++)
                    a += img.getRGB(x, y);
            return a;
        }
    }
    c[] s = new c[a[0].length()];
    int i = 0;
    for (char d : a[0].toCharArray())
        s[i++] = new c(d);
    Arrays.sort(s);
    for (c d : s)
        System.out.print(d.d);
}

ヒント:パブリック修飾子またはプライベート修飾子は可能な限り避けてください。ことは、不必要なバイトを節約する
masterX244

それをすべて忘れていた
マークジェロニムス14年

@MarkJeronimusこれは私がやってみようとしていた方法でしたが、FontRenderingContextを使ってみたかったのです。
魔法のタコUr

3

追記、381

まったくの楽しみのために、ここにまったく違うものがあります。とにかくほとんどのフォントはベクターなので、「ピクセルのカウント」は少し奇妙ですよね。グリフ形状面積を計算するのは正しい方法ですが、それほど簡単ではありません。別の方法としては、長方形をスキャンし、ポイントがグリフ形状の内側にあるときに「ヒット」をカウントすることができます。Postscriptには、この種のチェック用の演算子があります。ただし、実際には、スキャンと内部テストはピクセルをカウントする奇妙な方法です。

(%stdin)(r)file token pop/Courier 99 selectfont[1 index length{0}repeat]0 1 99{0 1 99{0 1 5 index length 1 sub{newpath 9 19 moveto 3 copy 7 index exch 1 getinterval false charpath infill{3 index exch 2 copy get 1 add put}{pop}ifelse}for pop}for pop}for 0 1 99 dup mul{0 1 3 index length 1 sub{dup 3 index exch get 2 index eq{3 index exch 1 getinterval print}{pop}ifelse}for pop}for

(%stdin) (r) file token pop
/Courier 99 selectfont
%/DejaVuSansMono 99 selectfont
%/UbuntuMono-Regular 99 selectfont
[ 1 index length {0} repeat ]   % str []
0 1 99 {
    0 1 99 {
        0 1 5 index length 1 sub {
            newpath 
            9 19 moveto
            3 copy              % str [] n m i n m i
            7 index exch        % str [] n m i n m str i
            1 getinterval       % str [] n m i n m s
            false charpath      % str [] n m i n m
            infill              % str [] n m i bool
            {3 index exch 2 copy get 1 add put} {pop} ifelse
        } for
        pop
    } for
    pop
} for
% un-comment next line to print number of 'hits' for each glyph
%
% dup {=} forall
%
% next is 'lazy sort'
0 1 99 dup mul {                % str [] i
    0 1 3 index length 1 sub {  % str [] i j
        dup 3 index exch        % str [] i j [] j
        get 2 index eq          % str [] i j bool
        {3 index exch 1 getinterval print} {pop} ifelse
    } for
    pop
} for
()=

次に、3つの異なるフォントの結果を示します(上記の選択はコメントを外すことができます)。

$ echo '(.-?@AByz01)' | gs -q -dBATCH d.ps
.-?1z0yA@B
$ echo '(.-?@AByz01)' | gs -q -dBATCH d.ps
.-?z1yA0B@
$ echo '(.-?@AByz01)' | gs -q -dBATCH d.ps
.-?1zyA0B@

カウントピクセル...カウントピクセル交差点...トマト.... tomahto ....
ジョナサン・ヴァンMatre

2

Perl(GDを使用)(159)

use GD;sub i{$i=new GD'Image 5,8;$B=colorExact$i 9,9,9;colorExact$i 0,0,0;char$i gdTinyFont,0,0,@_,1;$_=unpack"B*",wbmp$i 0;y/0//c}print+sort{i($a)-i($b)}@ARGV

使用法:

> perl dark.pl 1 2 3 @ # . , : ~ $ M i I s S
.,~:i13Is2S$M@#

編集:159文字に短縮


2

Java、584

うわー、これはこれを行うには良い言語ではありませんでした。

import java.awt.geom.*;import java.util.*;class F{static void n(final String f,List<Character> s){Collections.sort(s,new Comparator<Character>(){public int compare(Character a,Character b){return d(f,""+a) - d(f,""+b);}});}static int d(String f,String s){int i=0;PathIterator p=new java.awt.Font(f,0,12).createGlyphVector(((java.awt.Graphics2D)new java.awt.image.BufferedImage(8,8,2).getGraphics()).getFontRenderContext(),s).getGlyphOutline(0).getPathIterator(AffineTransform.getRotateInstance(0.0, 0.0));while(!p.isDone()){i+=p.currentSegment(new double[99])/2;p.next();}return i;}}

使用法:

import java.awt.geom.*;
import java.util.*;
public class F {
    public static void main(String[]args){
        List<Character> s = new ArrayList<Character>(0);
        s.add('@');
        s.add('+');
        s.add('.');
        s.add('0');
        n("Calibri", s);
        System.out.println(s);
    }
    static void n(final String f,List<Character> s){
        Collections.sort(s,new Comparator<Character>(){
            public int compare(Character a,Character b){
                return d(f,""+a) - d(f,""+b);
            }
        });
    }

    static int d(String f,String s){
        int i=0;
        PathIterator p=new java.awt.Font(f,0,12).createGlyphVector(((java.awt.Graphics2D)new java.awt.image.BufferedImage(8,8,2).getGraphics()).getFontRenderContext(),s).getGlyphOutline(0).getPathIterator(AffineTransform.getRotateInstance(0.0, 0.0));
        while(!p.isDone()){
            i+=p.currentSegment(new double[99])/2;
            p.next();
        }
        return i;
    }
}

このセットアップの結果:

[., +, 0, @]

ここで説明が必要な唯一の行:

PathIterator p=new java.awt.Font(f,0,12).createGlyphVector(((java.awt.Graphics2D)new java.awt.image.BufferedImage(8,8,2).getGraphics()).getFontRenderContext(),s).getGlyphOutline(0).getPathIterator(AffineTransform.getRotateInstance(0.0, 0.0));
  • 渡されたフォントで12ptフォントオブジェクトを初期化します。
  • 新しいBufferedImage obejctを作成して、GraphicsContextにリンクされたGraphics2Dオブジェクトを作成します。
  • 文字列sの2Dグラフィックスコンテキストのフォントレンダリングコンテキストを取得します。
  • 文字列の最初のグリフ(グリフのみ)を取得します。
  • パスイテレータ(ポイントのリスト)を取得します。

そして、この最後の作品はそれをまとめます...

while(!p.isDone()){
    i+=p.currentSegment(new double[99])/2;
    p.next();
}

すべてのポイントを反復処理し、ポイントのカウントを合計します。この密度情報はコンパレーターに戻され、ソートに使用されます。


1

R、195文字

A=strsplit(scan(,""),"")[[1]];cat(A[order(sapply(A,function(x){png('a',a='none',fa='monospace');frame();text(0,0,x);dev.off();sum(apply(png::readPNG('a'),c(1,2),function(x)any(x!=1)))}))],sep="")

コメントでインデント:

A=strsplit(scan(,""),"")[[1]] #Take characters as strings and split into single chars
cat(A[order(sapply(A,function(x){ #Apply the following function to each char and order accordingly
                 png('a',a='none',fa='monospace'); #Open empty png without antialiasing and with monospace font
                 frame(); #create empty plot
                 text(0,0,x); #add the char as text to the plot
                 dev.off(); #close png device
                 sum(apply(png::readPNG('a'), #read it back as rbga 3d matrix
                           c(1,2), #check every layer (R, G, B, A)
                           function(x)any(x!=1))) #if any are not 1, send TRUE
                 }))], #Sum all TRUEs
    sep="") #Prints to output

例:

> A=strsplit(scan(,""),"")[[1]];cat(A[order(sapply(A,function(x){png('a',a='none',fa='monospace');frame();text(0,0,x);dev.off();sum(apply(png::readPNG('a'),c(1,2),function(x)any(x!=1)))}))],sep="")
1: @+.0
2: 
Read 1 item
.+0@
> A=strsplit(scan(,""),"")[[1]];cat(A[order(sapply(A,function(x){png('a',a='none',fa='monospace');frame();text(0,0,x);dev.off();sum(apply(png::readPNG('a'),c(1,2),function(x)any(x!=1)))}))],sep="")
1: 1234567890
2: 
Read 1 item
1723450689

Rプロットでのフォントの配置はプラットフォームに依存するため、PCで動作することを保証できませんが、Mac(OS X 10.7.5、R 2.14.2)では動作します。


1

SmileBASIC、179の 176 173バイト

INPUT S$DIM Q$[0],A[0],Z[0]WHILE""<S$C$=POP(S$)GCLS
PUSH Q$,C$
GPUTCHR.,0,C$
GSAVE.,0,8,8,A,0S=0FOR I=0TO 63S=S+A[I]NEXT
PUSH Z,S
WEND
RSORT Z,Q$
WHILE LEN(Q$)?POP(Q$);
WEND

現在ロードされているフォントを使用します。フォントはでロードできますLOAD"GRPF:filename"

より読みやすいコード:

INPUT STRING$
DIM CHARS$[0],PIXELS[0],SIZES[0]
WHILE STRING$>""
 CHAR$=POP(STRING$)
 PUSH CHARS$,CHAR$
 GCLS
 GPUTCHR 0,0,CHAR$
 GSAVE 0,0,8,8,PIXELS
 SIZE=0
 FOR I=0 TO 63
  INC SIZE,PIXELS[I]
 NEXT
 PUSH SIZES,SIZE
WEND
RSORT SIZES,CHARS$
WHILE LEN(CHARS$)
 PRINT POP(CHARS$);
WEND

0

PHP-485

デモ:

$ php pcg-23362.php "@+.0"
.+0@

コード:

<?php $f='x.ttf';$d=array();foreach(str_split($argv[1]) as$_){$B=imagettfbbox(50,0,$f,$_);$w=abs($B[4]-$B[0]);$h=abs($B[5]-$B[1]);$im=imagecreate($w,$h);imagecolorallocate($im,255,255,255);imagettftext($im,50,0,0,$h-$B[1],imagecolorallocate($im,0,0,0),$f,$_);$b=$w*$h;for($x=0;$x<$w;$x++)for($y=0;$y<$h;$y++){$z=imagecolorsforindex($im,imagecolorat($im,$x,$y));$color=$z['red']*$z['green']*$z['blue'];$b-=$color/0x1000000;}$d[$_]=$b / ($w * $h);}asort($d);echo implode(array_keys($d));

ちょっと、X.TTFのコピーを送ってください...私が持っている最短のフォントはOCR Aです;-D-
ジョナサンヴァンマトレ

0

Python + freetype-py:147

import sys,freetype as F;f=F.Face('m.ttf');f.set_char_size(99);print(sorted([(f.load_char(c)or sum(f.glyph.bitmap.buffer),c)for c in raw_input()]))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.